diff --git a/public/main/admin/export_exercise_results.php b/public/main/admin/export_exercise_results.php
new file mode 100644
index 00000000000..15890bfc181
--- /dev/null
+++ b/public/main/admin/export_exercise_results.php
@@ -0,0 +1,237 @@
+ 'index.php', 'name' => get_lang('Administration')];
+
+$toolName = get_lang('Export all exercise results');
+
+// Get request parameters
+$sessionId = isset($_REQUEST['session_id']) ? (int) $_REQUEST['session_id'] : null;
+$courseId = isset($_GET['selected_course']) ? (int) $_GET['selected_course'] : null;
+$exerciseId = isset($_REQUEST['exerciseId']) ? (int) $_REQUEST['exerciseId'] : null;
+
+// Get repositories
+$user = api_get_user_entity(api_get_user_id());
+$sessionRepository = Container::getSessionRepository();
+$courseRepository = Container::getCourseRepository();
+$cQuizRepository = Container::getCQuizRepository();
+
+// Load sessions using repository
+$sessionSelectList = [0 => get_lang('Select')];
+try {
+ if (api_is_platform_admin()) {
+ $sessionList = $sessionRepository->findAll();
+ } else {
+ $sessionList = $sessionRepository->getSessionsByUser($user, api_get_url_entity())->getQuery()->getResult();
+ }
+
+ foreach ($sessionList as $session) {
+ $sessionSelectList[$session->getId()] = $session->getTitle();
+ }
+} catch (Exception $e) {
+ error_log('Error loading sessions: ' . $e->getMessage());
+ $sessionSelectList = [0 => get_lang('Error loading sessions')];
+}
+
+// Load courses using repository based on selected session
+$courseSelectList = [0 => get_lang('Select a session first')];
+if (!empty($sessionId) && $sessionId > 0) {
+ try {
+ $sessionEntity = $sessionRepository->find($sessionId);
+ if ($sessionEntity) {
+ $courseSelectList = [0 => get_lang('Select')];
+ $sessionCourses = $sessionEntity->getCourses();
+ foreach ($sessionCourses as $sessionCourse) {
+ $course = $sessionCourse->getCourse();
+ $courseSelectList[$course->getId()] = $course->getTitle();
+ }
+ } else {
+ $courseSelectList = [0 => get_lang('Session not found')];
+ }
+ } catch (Exception $e) {
+ error_log('Error loading courses for session ' . $sessionId . ': ' . $e->getMessage());
+ $courseSelectList = [0 => get_lang('Error loading courses')];
+ }
+}
+
+// Load exercises using repository based on selected course and session
+$exerciseSelectList = [0 => get_lang('Select a course first')];
+if (!empty($courseId) && $courseId > 0) {
+ try {
+ $courseEntity = $courseRepository->find($courseId);
+ $sessionEntity = $sessionId ? $sessionRepository->find($sessionId) : null;
+
+ if ($courseEntity) {
+ $exerciseList = $cQuizRepository->findAllByCourse($courseEntity, $sessionEntity);
+ $exerciseList = $exerciseList->getQuery()->getResult();
+
+ if (!empty($exerciseList)) {
+ $exerciseSelectList = [0 => get_lang('Select')];
+ foreach ($exerciseList as $exercise) {
+ $exerciseSelectList[$exercise->getIid()] = $exercise->getTitle();
+ }
+ } else {
+ $exerciseSelectList = [0 => get_lang('No exercises found')];
+ }
+ } else {
+ $exerciseSelectList = [0 => get_lang('Course not found')];
+ }
+ } catch (Exception $e) {
+ error_log('Error loading exercises for course ' . $courseId . ': ' . $e->getMessage());
+ $exerciseSelectList = [0 => get_lang('Error loading exercises')];
+ }
+}
+
+// JavaScript for form submission (page reload on change)
+$htmlHeadXtra[] = "
+
+";
+
+// Form creation
+$form = new FormValidator('export_all_results_form', 'POST');
+$form->addHeader(get_lang('Export all exercise results'));
+
+// Add form elements with Select2
+$form->addSelect(
+ 'session_id',
+ get_lang('Session'),
+ $sessionSelectList,
+ [
+ 'id' => 'session_id',
+ 'class' => 'select2 form-control'
+ ]
+)->setSelected($sessionId);
+
+if (empty($sessionId) || $sessionId == 0) {
+ $form->addSelect(
+ 'selected_course',
+ get_lang('Course'),
+ $courseSelectList,
+ [
+ 'id' => 'selected_course',
+ 'class' => 'select2 form-control',
+ 'disabled' => true
+ ]
+ );
+} else {
+ $form->addSelect(
+ 'selected_course',
+ get_lang('Course'),
+ $courseSelectList,
+ [
+ 'id' => 'selected_course',
+ 'class' => 'select2 form-control',
+ ]
+ )->setSelected($courseId);
+}
+
+if (empty($courseId) || $courseId == 0) {
+ $form->addSelect(
+ 'exerciseId',
+ get_lang('Exercise'),
+ $exerciseSelectList,
+ [
+ 'id' => 'exerciseId',
+ 'class' => 'select2 form-control',
+ 'disabled' => true
+ ]
+ );
+} else {
+ $form->addSelect(
+ 'exerciseId',
+ get_lang('Exercise'),
+ $exerciseSelectList,
+ [
+ 'id' => 'exerciseId',
+ 'class' => 'select2 form-control',
+ ]
+ )->setSelected($exerciseId);
+}
+
+// Date filters
+$form->addDateTimePicker('start_date', get_lang('Start date'));
+$form->addDateTimePicker('end_date', get_lang('End date'));
+
+// Validation rules
+$form->addRule('session_id', get_lang('Required field'), 'required');
+$form->addRule('selected_course', get_lang('Required field'), 'required');
+$form->addRule('exerciseId', get_lang('Required field'), 'required');
+
+// Export button
+$form->addButtonExport(get_lang('Export'), 'submit');
+
+// Process form submission
+if ($form->validate()) {
+ $values = $form->getSubmitValues();
+
+ $sessionId = (int) $values['session_id'];
+ $courseId = (int) $values['selected_course'];
+ $exerciseId = (int) $values['exerciseId'];
+
+ $filterDates = [
+ 'start_date' => (!empty($values['start_date']) ? $values['start_date'] : ''),
+ 'end_date' => (!empty($values['end_date']) ? $values['end_date'] : ''),
+ ];
+
+ try {
+ ExerciseLib::exportExerciseAllResultsZip($sessionId, $courseId, $exerciseId, $filterDates);
+ } catch (Exception $e) {
+ Display::addFlash(Display::return_message(get_lang('Export failed') . ': ' . $e->getMessage(), 'error'));
+ error_log('Exercise export error: ' . $e->getMessage());
+ }
+}
+
+Display::display_header($toolName);
+
+$form->display();
+
+Display::display_footer();
diff --git a/src/CoreBundle/Framework/Container.php b/src/CoreBundle/Framework/Container.php
index 6e5c80e1990..367c454b4f6 100644
--- a/src/CoreBundle/Framework/Container.php
+++ b/src/CoreBundle/Framework/Container.php
@@ -631,6 +631,11 @@ public static function getFormFactory(): FormFactory
return self::$container->get('form.factory');
}
+ public static function getCQuizRepository(): CQuizRepository
+ {
+ return self::$container->get(CQuizRepository::class);
+ }
+
public static function addFlash(string $message, string $type = 'success'): void
{
$type = match ($type) {