public static function process_page($feedbackid, $page, $responses = [], $goprevious = false, $courseid = 0) {
        global $USER, $SESSION;

        $params = array('feedbackid' => $feedbackid, 'page' => $page, 'responses' => $responses, 'goprevious' => $goprevious,
            'courseid' => $courseid);
        $params = self::validate_parameters(self::process_page_parameters(), $params);
        $warnings = array();
        $siteaftersubmit = $completionpagecontents = '';

        list($feedback, $course, $cm, $context, $completioncourse) = self::validate_feedback($params['feedbackid'],
            $params['courseid']);
        // Check we can do a new submission (or continue an existing).
        $feedbackcompletion = self::validate_feedback_access($feedback, $completioncourse, $cm, $context, true);

        // Create the $_POST object required by the feedback question engine.
        $_POST = array();
        foreach ($responses as $response) {
            // First check if we are handling array parameters.
            if (preg_match('/(.+)\[(.+)\]$/', $response['name'], $matches)) {
                $_POST[$matches[1]][$matches[2]] = $response['value'];
            } else {
                $_POST[$response['name']] = $response['value'];
            }
        }
        // Force fields.
        $_POST['id'] = $cm->id;
        $_POST['courseid'] = $courseid;
        $_POST['gopage'] = $params['page'];
        $_POST['_qf__mod_feedback_complete_form'] = 1;

        // Determine where to go, backwards or forward.
        if (!$params['goprevious']) {
            $_POST['gonextpage'] = 1;   // Even if we are saving values we need this set.
            if ($feedbackcompletion->get_next_page($params['page'], false) === null) {
                $_POST['savevalues'] = 1;   // If there is no next page, it means we are finishing the feedback.
            }
        }

        // Ignore sesskey (deep in some APIs), the request is already validated.
        $USER->ignoresesskey = true;
        feedback_init_feedback_session();
        $SESSION->feedback->is_started = true;

        $feedbackcompletion->process_page($params['page'], $params['goprevious']);
        $completed = $feedbackcompletion->just_completed();
        if ($completed) {
            $jumpto = 0;
            if ($feedback->page_after_submit) {
                $completionpagecontents = $feedbackcompletion->page_after_submit();
            }

            if ($feedback->site_after_submit) {
                $siteaftersubmit = feedback_encode_target_url($feedback->site_after_submit);
            }
        } else {
            $jumpto = $feedbackcompletion->get_jumpto();
        }

        $result = array(
            'jumpto' => $jumpto,
            'completed' => $completed,
            'completionpagecontents' => $completionpagecontents,
            'siteaftersubmit' => $siteaftersubmit,
            'warnings' => $warnings
        );
        return $result;
    }