set_user_id(api_get_user_id());
        $link->set_course_code($course_code);
        if (empty($category_id)) {
            return false;
        }
        $link->set_category_id($category_id);
        if ($link->needs_name_and_description()) {
            $link->set_name($resource_name);
        } else {
            $link->set_ref_id($resource_id);
        }
        $link->set_weight($weight);
        if ($link->needs_max()) {
            $link->set_max($max);
        }
        if ($link->needs_name_and_description()) {
            $link->set_description($resource_description);
        }
        $link->set_visible(empty($visible) ? 0 : 1);
        if (!empty($session_id)) {
            $link->set_session_id($session_id);
        }
        $link->add();
        return true;
    }
    /**
     * Update a resource weight.
     *
     * @param    int     Link/Resource ID
     * @param   string
     * @param float
     *
     * @return bool false on error, true on success
     */
    public static function updateResourceFromCourseGradebook(
        $link_id,
        $course_code,
        $weight
    ) {
        $link_id = (int) $link_id;
        if (!empty($link_id)) {
            $course_code = Database::escape_string($course_code);
            $sql = 'UPDATE '.Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK).'
                    SET weight = '."'".api_float_val($weight)."'".'
                    WHERE course_code = "'.$course_code.'" AND id = '.$link_id;
            Database::query($sql);
        }
        return true;
    }
    /**
     * Remove a resource from the unique gradebook of a given course.
     *
     * @param    int     Link/Resource ID
     *
     * @return bool false on error, true on success
     */
    public static function remove_resource_from_course_gradebook($link_id)
    {
        if (empty($link_id)) {
            return false;
        }
        // TODO find the corresponding category (the first one for this course, ordered by ID)
        $l = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
        $sql = "DELETE FROM $l WHERE id = ".(int) $link_id;
        Database::query($sql);
        return true;
    }
    /**
     * Block students.
     */
    public static function block_students()
    {
        $sessionId = api_get_session_id();
        if (empty($sessionId)) {
            if (!api_is_allowed_to_edit()) {
                api_not_allowed();
            }
        } else {
            $isCoach = api_is_coach(api_get_session_id(), api_get_course_int_id());
            if ($isCoach === false) {
                if (!api_is_allowed_to_edit()) {
                    api_not_allowed();
                }
            }
        }
    }
    /**
     * Builds an img tag for a gradebook item.
     */
    public static function build_type_icon_tag($kind, $attributes = [])
    {
        return Display::return_icon(
            self::get_icon_file_name($kind),
            ' ',
            $attributes,
            ICON_SIZE_SMALL
        );
    }
    /**
     * Returns the icon filename for a gradebook item.
     *
     * @param string $type value returned by a gradebookitem's get_icon_name()
     *
     * @return string
     */
    public static function get_icon_file_name($type)
    {
        switch ($type) {
            case 'cat':
                $icon = 'gradebook.png';
                break;
            case 'evalempty':
                $icon = 'empty_evaluation.png';
                break;
            case 'evalnotempty':
                $icon = 'no_empty_evaluation.png';
                break;
            case 'exercise':
            case LINK_EXERCISE:
                $icon = 'quiz.png';
                break;
            case 'learnpath':
            case LINK_LEARNPATH:
                $icon = 'learnpath.png';
                break;
            case 'studentpublication':
            case LINK_STUDENTPUBLICATION:
                $icon = 'works.gif';
                break;
            case 'link':
                $icon = 'link.gif';
                break;
            case 'forum':
            case LINK_FORUM_THREAD:
                $icon = 'forum.gif';
                break;
            case 'attendance':
            case LINK_ATTENDANCE:
                $icon = 'attendance.gif';
                break;
            case 'survey':
            case LINK_SURVEY:
                $icon = 'survey.gif';
                break;
            case 'dropbox':
            case LINK_DROPBOX:
                $icon = 'dropbox.gif';
                break;
            default:
                $icon = 'link.gif';
                break;
        }
        return $icon;
    }
    /**
     * Builds the course or platform admin icons to edit a category.
     *
     * @param Category $cat       category
     * @param Category $selectcat id of selected category
     *
     * @return string
     */
    public static function build_edit_icons_cat($cat, $selectcat)
    {
        $show_message = $cat->show_message_resource_delete($cat->get_course_code());
        $grade_model_id = $selectcat->get_grade_model_id();
        $selectcat = $selectcat->get_id();
        $modify_icons = null;
        if ($show_message === false) {
            $visibility_icon = ($cat->is_visible() == 0) ? 'invisible' : 'visible';
            $visibility_command = ($cat->is_visible() == 0) ? 'set_visible' : 'set_invisible';
            $modify_icons .= ''.
                Display::return_icon(
                    'view_more_stats.gif',
                    get_lang('Show'),
                    '',
                    ICON_SIZE_SMALL
                ).
                '';
            if (!api_is_allowed_to_edit(null, true)) {
                $modify_icons .= Display::url(
                    Display::return_icon(
                        'statistics.png',
                        get_lang('FlatView'),
                        '',
                        ICON_SIZE_SMALL
                    ),
                    'personal_stats.php?'.http_build_query([
                        'selectcat' => $cat->get_id(),
                    ]).'&'.api_get_cidreq(),
                    [
                        'class' => 'ajax',
                        'data-title' => get_lang('FlatView'),
                    ]
                );
            }
            $courseParams = api_get_cidreq_params(
                $cat->get_course_code(),
                $cat->get_session_id()
            );
            if (api_is_allowed_to_edit(null, true)) {
                // Locking button
                if (api_get_setting('gradebook_locking_enabled') == 'true') {
                    if ($cat->is_locked()) {
                        if (api_is_platform_admin()) {
                            $modify_icons .= ' '.
                                Display::return_icon('lock.png', get_lang('UnLockEvaluation'), '', ICON_SIZE_SMALL).'';
                        } else {
                            $modify_icons .= ' '.
                                Display::return_icon('lock_na.png', get_lang('GradebookLockedAlert'), '', ICON_SIZE_SMALL).'';
                        }
                        $modify_icons .= ' '.Display::return_icon('pdf.png', get_lang('ExportToPDF'), '', ICON_SIZE_SMALL).'';
                    } else {
                        $modify_icons .= ' '.
                            Display::return_icon('unlock.png', get_lang('LockEvaluation'), '', ICON_SIZE_SMALL).'';
                        $modify_icons .= ' '.
                            Display::return_icon('pdf_na.png', get_lang('ExportToPDF'), '', ICON_SIZE_SMALL).'';
                    }
                }
                if (empty($grade_model_id) || $grade_model_id == -1) {
                    if ($cat->is_locked() && !api_is_platform_admin()) {
                        $modify_icons .= Display::return_icon(
                            'edit_na.png',
                            get_lang('Modify'),
                            '',
                            ICON_SIZE_SMALL
                        );
                    } else {
                        $modify_icons .= ''.
                            Display::return_icon(
                                'edit.png',
                                get_lang('Modify'),
                                '',
                                ICON_SIZE_SMALL
                            ).'';
                    }
                }
                $modify_icons .= ''.
                    Display::return_icon(
                        'percentage.png',
                        get_lang('EditAllWeights'),
                        '',
                        ICON_SIZE_SMALL
                    ).'';
                $modify_icons .= ''.
                    Display::return_icon(
                        'statistics.png',
                        get_lang('FlatView'),
                        '',
                        ICON_SIZE_SMALL
                    ).'';
                $modify_icons .= ' '.
                    Display::return_icon(
                        $visibility_icon.'.png',
                        get_lang('Visible'),
                        '',
                        ICON_SIZE_SMALL
                    ).'';
                if ($cat->is_locked() && !api_is_platform_admin()) {
                    $modify_icons .= Display::return_icon(
                        'delete_na.png',
                        get_lang('DeleteAll'),
                        '',
                        ICON_SIZE_SMALL
                    );
                } else {
                    $modify_icons .= ' '.
                        Display::return_icon(
                            'delete.png',
                            get_lang('DeleteAll'),
                            '',
                            ICON_SIZE_SMALL
                        ).
                        '';
                }
            }
            return $modify_icons;
        }
    }
    /**
     * Builds the course or platform admin icons to edit an evaluation.
     *
     * @param Evaluation $eval      evaluation object
     * @param int        $selectcat id of selected category
     *
     * @return string
     */
    public static function build_edit_icons_eval($eval, $selectcat)
    {
        $is_locked = $eval->is_locked();
        $eval->get_course_code();
        $cat = new Category();
        $message_eval = $cat->show_message_resource_delete($eval->get_course_code());
        $courseParams = api_get_cidreq_params($eval->get_course_code(), $eval->getSessionId());
        if ($message_eval === false && api_is_allowed_to_edit(null, true)) {
            $visibility_icon = $eval->is_visible() == 0 ? 'invisible' : 'visible';
            $visibility_command = $eval->is_visible() == 0 ? 'set_visible' : 'set_invisible';
            if ($is_locked && !api_is_platform_admin()) {
                $modify_icons = Display::return_icon(
                    'edit_na.png',
                    get_lang('Modify'),
                    '',
                    ICON_SIZE_SMALL
                );
            } else {
                $modify_icons = ''.
                    Display::return_icon(
                        'edit.png',
                        get_lang('Modify'),
                        '',
                        ICON_SIZE_SMALL
                    ).
                    '';
            }
            $modify_icons .= ' '.
                Display::return_icon(
                    $visibility_icon.'.png',
                    get_lang('Visible'),
                    '',
                    ICON_SIZE_SMALL
                ).
                '';
            if (api_is_allowed_to_edit(null, true)) {
                $modify_icons .= ' '.
                    Display::return_icon(
                        'history.png',
                        get_lang('GradebookQualifyLog'),
                        '',
                        ICON_SIZE_SMALL
                    ).
                    '';
                $allowStats = api_get_configuration_value('allow_gradebook_stats');
                if ($allowStats) {
                    $modify_icons .= Display::url(
                        Display::return_icon('reload.png', get_lang('GenerateStats')),
                        api_get_self().'?itemId='.$eval->get_id().'&action=generate_eval_stats&selectcat='.$selectcat.'&'.$courseParams
                    );
                }
            }
            if ($is_locked && !api_is_platform_admin()) {
                $modify_icons .= ' '.
                    Display::return_icon(
                        'delete_na.png',
                        get_lang('Delete'),
                        '',
                        ICON_SIZE_SMALL
                    );
            } else {
                $modify_icons .= ' '.
                    Display::return_icon(
                        'delete.png',
                        get_lang('Delete'),
                        '',
                        ICON_SIZE_SMALL
                    ).
                    '';
            }
            return $modify_icons;
        }
    }
    /**
     * Builds the course or platform admin icons to edit a link.
     *
     * @param AbstractLink $link
     * @param int          $selectcat id of selected category
     *
     * @return string
     */
    public static function build_edit_icons_link($link, $selectcat)
    {
        $cat = new Category();
        $message_link = $cat->show_message_resource_delete($link->get_course_code());
        $is_locked = $link->is_locked();
        $modify_icons = null;
        if (!api_is_allowed_to_edit(null, true)) {
            return null;
        }
        $courseParams = api_get_cidreq_params(
            $link->get_course_code(),
            $link->get_session_id()
        );
        if ($message_link === false) {
            $visibility_icon = $link->is_visible() == 0 ? 'invisible' : 'visible';
            $visibility_command = $link->is_visible() == 0 ? 'set_visible' : 'set_invisible';
            if ($is_locked && !api_is_platform_admin()) {
                $modify_icons = Display::return_icon(
                    'edit_na.png',
                    get_lang('Modify'),
                    '',
                    ICON_SIZE_SMALL
                );
            } else {
                $modify_icons = ''.
                    Display::return_icon(
                        'edit.png',
                        get_lang('Modify'),
                        '',
                        ICON_SIZE_SMALL
                    ).
                    '';
            }
            $modify_icons .= ' '.
                Display::return_icon(
                    $visibility_icon.'.png',
                    get_lang('Visible'),
                    '',
                    ICON_SIZE_SMALL
                ).
                '';
            $modify_icons .= ' '.
                Display::return_icon(
                    'history.png',
                    get_lang('GradebookQualifyLog'),
                    '',
                    ICON_SIZE_SMALL
                ).
                '';
            $allowStats = api_get_configuration_value('allow_gradebook_stats');
            if ($allowStats && $link->get_type() == LINK_EXERCISE) {
                $modify_icons .= Display::url(
                    Display::return_icon('reload.png', get_lang('GenerateStats')),
                    api_get_self().'?itemId='.$link->get_id().'&action=generate_link_stats&selectcat='.$selectcat.'&'.$courseParams
                );
            }
            //If a work is added in a gradebook you can only delete the link in the work tool
            if ($is_locked && !api_is_platform_admin()) {
                $modify_icons .= ' '.
                    Display::return_icon(
                        'delete_na.png',
                        get_lang('Delete'),
                        '',
                        ICON_SIZE_SMALL
                    );
            } else {
                $modify_icons .= ' '.
                    Display::return_icon(
                        'delete.png',
                        get_lang('Delete'),
                        '',
                        ICON_SIZE_SMALL
                    ).
                    '';
            }
            return $modify_icons;
        }
    }
    /**
     * Checks if a resource is in the unique gradebook of a given course.
     *
     * @param string $course_code   Course code
     * @param int    $resource_type Resource type (use constants defined in linkfactory.class.php)
     * @param int    $resource_id   Resource ID in the corresponding tool
     * @param int    $session_id    Session ID (optional -  0 if not defined)
     *
     * @return array false on error or array of resource
     */
    public static function isResourceInCourseGradebook(
        $course_code,
        $resource_type,
        $resource_id,
        $session_id = 0
    ) {
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
        $course_code = Database::escape_string($course_code);
        $sql = "SELECT * FROM $table l
                WHERE
                    course_code = '$course_code' AND
                    type = ".(int) $resource_type." AND
                    ref_id = ".(int) $resource_id;
        $res = Database::query($sql);
        if (Database::num_rows($res) < 1) {
            return false;
        }
        $row = Database::fetch_array($res, 'ASSOC');
        return $row;
    }
    /**
     * Remove a resource from the unique gradebook of a given course.
     *
     * @param    int     Link/Resource ID
     *
     * @return bool false on error, true on success
     */
    public static function get_resource_from_course_gradebook($link_id)
    {
        if (empty($link_id)) {
            return false;
        }
        // TODO find the corresponding category (the first one for this course, ordered by ID)
        $l = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
        $sql = "SELECT * FROM $l WHERE id = ".(int) $link_id;
        $res = Database::query($sql);
        $row = [];
        if (Database::num_rows($res) > 0) {
            $row = Database::fetch_array($res, 'ASSOC');
        }
        return $row;
    }
    /**
     * Return the course id.
     *
     * @param    int
     *
     * @return string
     */
    public static function get_course_id_by_link_id($id_link)
    {
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
        $tbl_grade_links = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
        $id_link = (int) $id_link;
        $sql = 'SELECT c.id FROM '.$course_table.' c
                INNER JOIN '.$tbl_grade_links.' l
                ON c.code = l.course_code
                WHERE l.id='.$id_link.' OR l.category_id='.$id_link;
        $res = Database::query($sql);
        $array = Database::fetch_array($res, 'ASSOC');
        return $array['id'];
    }
    /**
     * @param $type
     *
     * @return string
     */
    public static function get_table_type_course($type)
    {
        global $table_evaluated;
        return Database::get_course_table($table_evaluated[$type][0]);
    }
    /**
     * @param Category $cat
     * @param $users
     * @param $alleval
     * @param $alllinks
     * @param $params
     * @param null $mainCourseCategory
     *
     * @return array
     */
    public static function get_printable_data(
        $cat,
        $users,
        $alleval,
        $alllinks,
        $params,
        $mainCourseCategory = null
    ) {
        $datagen = new FlatViewDataGenerator(
            $users,
            $alleval,
            $alllinks,
            $params,
            $mainCourseCategory
        );
        $offset = isset($_GET['offset']) ? (int) $_GET['offset'] : 0;
        // step 2: generate rows: students
        $datagen->category = $cat;
        $count = (($offset + 10) > $datagen->get_total_items_count()) ? ($datagen->get_total_items_count() - $offset) : GRADEBOOK_ITEM_LIMIT;
        $header_names = $datagen->get_header_names($offset, $count, true);
        $data_array = $datagen->get_data(
            FlatViewDataGenerator::FVDG_SORT_LASTNAME,
            0,
            null,
            $offset,
            $count,
            true,
            true
        );
        $result = [];
        foreach ($data_array as $data) {
            $result[] = array_slice($data, 1);
        }
        $return = [$header_names, $result];
        return $return;
    }
    /**
     * XML-parser: handle character data.
     */
    public static function character_data($parser, $data)
    {
        global $current_value;
        $current_value = $data;
    }
    public static function overwritescore($resid, $importscore, $eval_max)
    {
        $result = Result::load($resid);
        if ($importscore > $eval_max) {
            header('Location: gradebook_view_result.php?selecteval='.Security::remove_XSS($_GET['selecteval']).'&overwritemax=');
            exit;
        }
        $result[0]->set_score($importscore);
        $result[0]->save();
        unset($result);
    }
    /**
     * register user info about certificate.
     *
     * @param int    $cat_id            The category id
     * @param int    $user_id           The user id
     * @param float  $score_certificate The score obtained for certified
     * @param string $date_certificate  The date when you obtained the certificate
     */
    public static function registerUserInfoAboutCertificate(
        $cat_id,
        $user_id,
        $score_certificate,
        $date_certificate
    ) {
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
        $cat_id = (int) $cat_id;
        $user_id = (int) $user_id;
        $sql = "SELECT COUNT(id) as count
                FROM $table gc
                WHERE gc.cat_id = $cat_id AND user_id = $user_id ";
        $rs_exist = Database::query($sql);
        $row = Database::fetch_array($rs_exist);
        if ($row['count'] == 0) {
            $params = [
                'cat_id' => $cat_id,
                'user_id' => $user_id,
                'score_certificate' => $score_certificate,
                'created_at' => $date_certificate,
            ];
            Database::insert($table, $params);
        }
    }
    /**
     * Get date of user certificate.
     *
     * @param int $cat_id  The category id
     * @param int $user_id The user id
     *
     * @return Datetime The date when you obtained the certificate
     */
    public static function get_certificate_by_user_id($cat_id, $user_id)
    {
        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
        $cat_id = (int) $cat_id;
        $user_id = (int) $user_id;
        $sql = "SELECT * FROM $table
                WHERE cat_id = $cat_id AND user_id = $user_id ";
        $result = Database::query($sql);
        $row = Database::fetch_array($result, 'ASSOC');
        return $row;
    }
    /**
     * Get list of users certificates.
     *
     * @param int   $cat_id   The category id
     * @param array $userList Only users in this list
     *
     * @return array
     */
    public static function get_list_users_certificates($cat_id = null, $userList = [])
    {
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
        $sql = 'SELECT DISTINCT u.user_id, u.lastname, u.firstname, u.username
                FROM '.$table_user.' u
                INNER JOIN '.$table_certificate.' gc
                ON u.user_id=gc.user_id ';
        if (!is_null($cat_id) && $cat_id > 0) {
            $sql .= ' WHERE cat_id='.intval($cat_id);
        }
        if (!empty($userList)) {
            $userList = array_map('intval', $userList);
            $userListCondition = implode("','", $userList);
            $sql .= " AND u.user_id IN ('$userListCondition')";
        }
        $sql .= ' ORDER BY '.(api_sort_by_first_name() ? 'u.firstname' : 'u.lastname');
        $rs = Database::query($sql);
        $list_users = [];
        while ($row = Database::fetch_array($rs)) {
            $list_users[] = $row;
        }
        return $list_users;
    }
    /**
     * Gets the certificate list by user id.
     *
     * @param int $user_id The user id
     * @param int $cat_id  The category id
     *
     * @return array
     */
    public static function get_list_gradebook_certificates_by_user_id(
        $user_id,
        $cat_id = null
    ) {
        $user_id = (int) $user_id;
        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
        $sql = 'SELECT
                    gc.score_certificate,
                    gc.created_at,
                    gc.path_certificate,
                    gc.cat_id,
                    gc.user_id,
                    gc.id
                FROM  '.$table_certificate.' gc
                WHERE gc.user_id = "'.$user_id.'" ';
        if (!is_null($cat_id) && $cat_id > 0) {
            $sql .= ' AND cat_id='.intval($cat_id);
        }
        $rs = Database::query($sql);
        $list = [];
        while ($row = Database::fetch_array($rs)) {
            $list[] = $row;
        }
        return $list;
    }
    /**
     * @param int    $user_id
     * @param string $course_code
     * @param int    $sessionId
     * @param bool   $is_preview
     * @param bool   $hide_print_button
     *
     * @return array
     */
    public static function get_user_certificate_content(
        $user_id,
        $course_code,
        $sessionId,
        $is_preview = false,
        $hide_print_button = false
    ) {
        // Generate document HTML
        $content_html = DocumentManager::replace_user_info_into_html(
            $user_id,
            $course_code,
            $sessionId,
            $is_preview
        );
        $new_content_html = isset($content_html['content']) ? $content_html['content'] : null;
        $variables = isset($content_html['variables']) ? $content_html['variables'] : null;
        $path_image = api_get_path(WEB_COURSE_PATH).api_get_course_path($course_code).'/document/images/gallery';
        $new_content_html = str_replace('../images/gallery', $path_image, $new_content_html);
        $path_image_in_default_course = api_get_path(WEB_CODE_PATH).'default_course_document';
        $new_content_html = str_replace('/main/default_course_document', $path_image_in_default_course, $new_content_html);
        $new_content_html = str_replace(SYS_CODE_PATH.'img/', api_get_path(WEB_IMG_PATH), $new_content_html);
        //add print header
        if (!$hide_print_button) {
            $print = '';
            $print .= Display::div(
                Display::url(
                    Display::return_icon('printmgr.gif', get_lang('Print')),
                    'javascript:void()',
                    ['onclick' => 'window.print();']
                ),
                ['id' => 'print_div']
            );
            $print .= '