@@ -255,14 +255,13 @@ function complete_missing_data(array $user): array
255255/**
256256 * Save the imported data.
257257 *
258- * @uses \global variable $inserted_in_course, which returns the list of
259- * courses the user was inserted in
258+ * @uses global $inserted_in_course, which returns the list of courses the user was inserted in
259+ * @param array $users
260+ * @param bool $sendMail
261+ * @param string|null $targetFolder
262+ * @return array The $users array, with 'message' and (for reused users) 'id' set
260263 */
261- function save_data (
262- array $ users ,
263- bool $ sendMail = false ,
264- ?string $ targetFolder = null
265- ): array {
264+ function save_data (array $ users , bool $ sendMail = false , ?string $ targetFolder = null ): array {
266265 global $ inserted_in_course , $ extra_fields ;
267266
268267 // Not all scripts declare the $inserted_in_course array (although they should).
@@ -281,107 +280,150 @@ function save_data(
281280
282281 $ optionsByField = [];
283282
283+ // which extra‑field variable are we validating on?
284+ $ uniqueField = api_get_configuration_value ('extra_field_to_validate_on_user_registration ' );
285+
284286 foreach ($ users as &$ user ) {
285287 if ($ user ['has_error ' ]) {
286288 $ userError [] = $ user ;
287289 continue ;
288290 }
289291
290- $ user = complete_missing_data ($ user );
291- $ user ['Status ' ] = api_status_key ($ user ['Status ' ]);
292- $ redirection = $ user ['Redirection ' ] ?? '' ;
292+ $ returnMessage = '' ;
293+ $ user_id = null ;
294+
295+ // 1) If the CSV row has that unique extra‑field, try to look up an existing user
296+ if (!empty ($ uniqueField ) && !empty ($ user [$ uniqueField ])) {
297+ // pass true to getUserId mode
298+ $ existing = UserManager::isExtraFieldValueUniquePerUrl ($ user [$ uniqueField ], true );
299+ if ($ existing !== null ) {
300+ // existing user found → reuse
301+ $ user_id = $ existing ;
302+ $ returnMessage = Display::return_message (
303+ sprintf (
304+ 'An existing user with the same %s was found (ID %d), enrolling instead of creating. ' ,
305+ $ uniqueField ,
306+ $ existing
307+ ),
308+ 'info '
309+ );
310+ }
311+ }
293312
294- $ user_id = UserManager::create_user (
295- $ user ['FirstName ' ],
296- $ user ['LastName ' ],
297- $ user ['Status ' ],
298- $ user ['Email ' ],
299- $ user ['UserName ' ],
300- $ user ['Password ' ],
301- $ user ['OfficialCode ' ],
302- $ user ['language ' ],
303- $ user ['PhoneNumber ' ],
304- '' ,
305- $ user ['AuthSource ' ],
306- $ user ['ExpiryDate ' ],
307- 1 ,
308- 0 ,
309- null ,
310- null ,
311- $ sendMail ,
312- false ,
313- '' ,
314- false ,
315- null ,
316- null ,
317- null ,
318- $ redirection
319- );
313+ // 2) If not found, go through normal creation
314+ if ($ user_id === null ) {
315+ // fill in missing fields, generate password, etc.
316+ $ user = complete_missing_data ($ user );
317+ $ user ['Status ' ] = api_status_key ($ user ['Status ' ]);
318+ $ redirection = $ user ['Redirection ' ] ?? '' ;
319+
320+ $ user_id = UserManager::create_user (
321+ $ user ['FirstName ' ],
322+ $ user ['LastName ' ],
323+ $ user ['Status ' ],
324+ $ user ['Email ' ],
325+ $ user ['UserName ' ],
326+ $ user ['Password ' ],
327+ $ user ['OfficialCode ' ],
328+ $ user ['language ' ],
329+ $ user ['PhoneNumber ' ],
330+ '' ,
331+ $ user ['AuthSource ' ],
332+ $ user ['ExpiryDate ' ],
333+ 1 ,
334+ 0 ,
335+ null ,
336+ null ,
337+ $ sendMail ,
338+ false ,
339+ '' ,
340+ false ,
341+ null ,
342+ null ,
343+ null ,
344+ $ redirection
345+ );
320346
321- if ($ user_id ) {
322- $ returnMessage = Display::return_message (get_lang ('UserAdded ' ), 'success ' );
323-
324- if (isset ($ user ['Courses ' ]) && is_array ($ user ['Courses ' ])) {
325- foreach ($ user ['Courses ' ] as $ course ) {
326- if (CourseManager::course_exists ($ course )) {
327- $ result = CourseManager::subscribeUser ($ user_id , $ course , $ user ['Status ' ]);
328- if ($ result ) {
329- $ course_info = api_get_course_info ($ course );
330- $ inserted_in_course [$ course ] = $ course_info ['title ' ];
331- }
332- }
333- }
347+ if ($ user_id ) {
348+ $ returnMessage = Display::return_message (get_lang ('UserAdded ' ), 'success ' );
349+ } else {
350+ $ returnMessage = Display::return_message (get_lang ('Error ' ), 'error ' );
351+ $ userWarning [] = $ user ;
352+ $ user ['message ' ] = $ returnMessage ;
353+ continue ;
334354 }
355+ }
335356
336- if (isset ($ user ['Sessions ' ]) && is_array ($ user ['Sessions ' ])) {
337- foreach ($ user ['Sessions ' ] as $ sessionId ) {
338- $ sessionInfo = api_get_session_info ($ sessionId );
339- if (!empty ($ sessionInfo )) {
340- SessionManager::subscribeUsersToSession (
341- $ sessionId ,
342- [$ user_id ],
343- SESSION_VISIBLE_READ_ONLY ,
344- false
345- );
357+ // 3) At this point $user_id is either reused or newly created.
358+ // Enroll in courses:
359+ if (isset ($ user ['Courses ' ]) && is_array ($ user ['Courses ' ])) {
360+ foreach ($ user ['Courses ' ] as $ course ) {
361+ if (CourseManager::course_exists ($ course )) {
362+ $ result = CourseManager::subscribeUser ($ user_id , $ course , $ user ['Status ' ]);
363+ if ($ result ) {
364+ $ info = api_get_course_info ($ course );
365+ $ inserted_in_course [$ course ] = $ info ['title ' ];
346366 }
347367 }
348368 }
369+ }
349370
350- if (!empty ($ user ['ClassId ' ])) {
351- $ classId = explode ('| ' , trim ($ user ['ClassId ' ]));
352- foreach ($ classId as $ id ) {
353- $ usergroup ->subscribe_users_to_usergroup ($ id , [$ user_id ], false );
371+ // 4) Enroll in sessions:
372+ if (isset ($ user ['Sessions ' ]) && is_array ($ user ['Sessions ' ])) {
373+ foreach ($ user ['Sessions ' ] as $ sessionId ) {
374+ $ sessionInfo = api_get_session_info ($ sessionId );
375+ if (!empty ($ sessionInfo )) {
376+ SessionManager::subscribeUsersToSession (
377+ $ sessionId ,
378+ [$ user_id ],
379+ SESSION_VISIBLE_READ_ONLY ,
380+ false
381+ );
354382 }
355383 }
384+ }
356385
357- // We are sure that the extra field exists.
358- foreach ($ extra_fields as $ extras ) {
359- if (!isset ($ user [$ extras [1 ]])) {
360- continue ;
361- }
362-
363- $ key = $ extras [1 ];
364- $ value = $ user [$ key ];
386+ // 5) Subscribe to usergroups:
387+ if (!empty ($ user ['ClassId ' ])) {
388+ $ classIds = explode ('| ' , trim ($ user ['ClassId ' ]));
389+ foreach ($ classIds as $ id ) {
390+ $ usergroup ->subscribe_users_to_usergroup ($ id , [$ user_id ], false );
391+ }
392+ }
365393
366- if (!array_key_exists ($ key , $ optionsByField )) {
367- $ optionsByField [$ key ] = $ efo ->getOptionsByFieldVariable ($ key );
394+ // 6) Update extra‑field values (for newly created or even reused users):
395+ foreach ($ extra_fields as $ extras ) {
396+ $ fieldVar = $ extras [1 ];
397+ $ matchedKey = null ;
398+ foreach ($ user as $ colName => $ colVal ) {
399+ if (strtolower ($ colName ) === strtolower ($ fieldVar )) {
400+ $ matchedKey = $ colName ;
401+ break ;
368402 }
403+ }
404+ if ($ matchedKey === null ) {
405+ continue ;
406+ }
369407
370- /** @var ExtraFieldOptions $option */
371- foreach ($ optionsByField [$ key ] as $ option ) {
372- if ($ option ->getDisplayText () === $ value ) {
373- $ value = $ option ->getValue ();
374- }
408+ $ value = $ user [$ matchedKey ];
409+ if (!array_key_exists ($ matchedKey , $ optionsByField )) {
410+ $ optionsByField [$ matchedKey ] = $ efo ->getOptionsByFieldVariable ($ matchedKey );
411+ }
412+ /** @var ExtraFieldOptions $option */
413+ foreach ($ optionsByField [$ matchedKey ] as $ option ) {
414+ if ($ option ->getDisplayText () === $ value ) {
415+ $ value = $ option ->getValue ();
416+ break ;
375417 }
376-
377- UserManager::update_extra_field_value ($ user_id , $ key , $ value );
378418 }
379- $ userSaved [] = $ user ;
380- } else {
381- $ returnMessage = Display::return_message (get_lang ('Error ' ), 'warning ' );
382- $ userWarning [] = $ user ;
419+
420+ UserManager::update_extra_field_value ($ user_id , $ matchedKey , $ value );
383421 }
422+
423+ // 7) Record success
424+ $ user ['id ' ] = $ user_id ;
384425 $ user ['message ' ] = $ returnMessage ;
426+ $ userSaved [] = $ user ;
385427 }
386428
387429 // Save with success, error and warning users
@@ -708,6 +750,25 @@ function processUsers(array &$users, bool $sendMail, ?string $targetFolder = nul
708750
709751 Session::erase ('user_import_data_ ' .$ userId );
710752 $ users = Import::csvToArray ($ _FILES ['import_file ' ]['tmp_name ' ]);
753+
754+ $ uniqueField = api_get_configuration_value ('extra_field_to_validate_on_user_registration ' );
755+ if (!empty ($ uniqueField ) && !empty ($ users )) {
756+ $ firstRow = reset ($ users );
757+ $ csvHeader = array_keys ($ firstRow );
758+ $ csvHeaderLower = array_map ('trim ' , array_map ('strtolower ' , $ csvHeader ));
759+
760+ if (!in_array ($ uniqueField , $ csvHeaderLower , true )) {
761+ Display::addFlash (
762+ Display::return_message (
763+ sprintf ('The column "%s" is required in the CSV for this platform ' , $ uniqueField ),
764+ 'error '
765+ )
766+ );
767+ header ('Location: ' . api_get_self ());
768+ exit ;
769+ }
770+ }
771+
711772 $ users = parse_csv_data (
712773 $ users ,
713774 $ cleanFileName ,
0 commit comments