public function export_user_data(contextlist_collection $contextlistcollection) {
        $progress = static::get_log_tracer();

        $a = (object) [
            'total' => count($contextlistcollection),
            'progress' => 0,
            'component' => '',
            'datetime' => userdate(time()),
        ];

        // Export for the various components/contexts.
        $progress->output(get_string('trace:exportingapproved', 'core_privacy', $a), 1);
        foreach ($contextlistcollection as $approvedcontextlist) {

            if (!$approvedcontextlist instanceof \core_privacy\local\request\approved_contextlist) {
                throw new \moodle_exception('Contextlist must be an approved_contextlist');
            }

            $component = $approvedcontextlist->get_component();
            $a->component = $component;
            $a->progress++;
            $a->datetime = userdate(time());
            $progress->output(get_string('trace:processingcomponent', 'core_privacy', $a), 2);

            // Core user data providers.
            if ($this->component_implements($component, core_user_data_provider::class)) {
                if (count($approvedcontextlist)) {
                    // This plugin has data it knows about. It is responsible for storing basic data about anything it is
                    // told to export.
                    $this->handled_component_class_callback($component, core_user_data_provider::class,
                        'export_user_data', [$approvedcontextlist]);
                }
            } else if (!$this->component_implements($component, context_aware_provider::class)) {
                // This plugin does not know that it has data - export the shared data it doesn't know about.
                local\request\helper::export_data_for_null_provider($approvedcontextlist);
            }
        }
        $progress->output(get_string('trace:done', 'core_privacy'), 1);

        // Check each component for non contextlist items too.
        $components = $this->get_component_list();
        $a->total = count($components);
        $a->progress = 0;
        $a->datetime = userdate(time());
        $progress->output(get_string('trace:exportingrelated', 'core_privacy', $a), 1);
        foreach ($components as $component) {
            $a->component = $component;
            $a->progress++;
            $a->datetime = userdate(time());
            $progress->output(get_string('trace:processingcomponent', 'core_privacy', $a), 2);
            // Core user preference providers.
            $this->handled_component_class_callback($component, user_preference_provider::class,
                'export_user_preferences', [$contextlistcollection->get_userid()]);

            // Contextual information providers. Give each component a chance to include context information based on the
            // existence of a child context in the contextlist_collection.
            $this->handled_component_class_callback($component, context_aware_provider::class,
                'export_context_data', [$contextlistcollection]);
        }
        $progress->output(get_string('trace:done', 'core_privacy'), 1);

        $progress->output(get_string('trace:finalisingexport', 'core_privacy'), 1);
        $location = local\request\writer::with_context(\context_system::instance())->finalise_content();

        $progress->output(get_string('trace:exportcomplete', 'core_privacy'), 1);
        return $location;
    }