public static function launch_attempt($lessonid, $password = '', $pageid = 0, $review = false) {
        global $CFG, $USER;

        $params = array('lessonid' => $lessonid, 'password' => $password, 'pageid' => $pageid, 'review' => $review);
        $params = self::validate_parameters(self::launch_attempt_parameters(), $params);
        $warnings = array();

        list($lesson, $course, $cm, $context, $lessonrecord) = self::validate_lesson($params['lessonid']);
        self::validate_attempt($lesson, $params);

        $newpageid = 0;
        // Starting a new lesson attempt.
        if (empty($params['pageid'])) {
            // Check if there is a recent timer created during the active session.
            $alreadystarted = false;
            if ($timers = $lesson->get_user_timers($USER->id, 'starttime DESC', '*', 0, 1)) {
                $timer = array_shift($timers);
                $endtime = $lesson->timelimit > 0 ? min($CFG->sessiontimeout, $lesson->timelimit) : $CFG->sessiontimeout;
                if (!$timer->completed && $timer->starttime > time() - $endtime) {
                    $alreadystarted = true;
                }
            }
            if (!$alreadystarted && !$lesson->can_manage()) {
                $lesson->start_timer();
            }
        } else {
            if ($params['pageid'] == LESSON_EOL) {
                throw new moodle_exception('endoflesson', 'lesson');
            }
            $timer = $lesson->update_timer(true, true);
            if (!$lesson->check_time($timer)) {
                throw new moodle_exception('eolstudentoutoftime', 'lesson');
            }
        }
        $messages = self::format_lesson_messages($lesson);

        $result = array(
            'status' => true,
            'messages' => $messages,
            'warnings' => $warnings,
        );
        return $result;
    }