@@ -21,6 +21,7 @@ import { CoreSitesProvider, CoreSitesReadingStrategy } from '@providers/sites';
2121import { CoreSyncProvider } from '@providers/sync' ;
2222import { CoreTextUtilsProvider } from '@providers/utils/text' ;
2323import { CoreTimeUtilsProvider } from '@providers/utils/time' ;
24+ import { CoreUtils } from '@providers/utils/utils' ;
2425import { CoreCourseProvider } from '@core/course/providers/course' ;
2526import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper' ;
2627import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate' ;
@@ -288,16 +289,6 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
288289 syncQuiz ( quiz : any , askPreflight ?: boolean , siteId ?: string ) : Promise < AddonModQuizSyncResult > {
289290 siteId = siteId || this . sitesProvider . getCurrentSiteId ( ) ;
290291
291- const warnings = [ ] ;
292- const courseId = quiz . course ;
293- const modOptions = {
294- cmId : quiz . coursemodule ,
295- readingStrategy : CoreSitesReadingStrategy . OnlyNetwork ,
296- siteId,
297- } ;
298- let syncPromise ;
299- let preflightData ;
300-
301292 if ( this . isSyncing ( quiz . id , siteId ) ) {
302293 // There's already a sync ongoing for this quiz, return the promise.
303294 return this . getOngoingSync ( quiz . id , siteId ) ;
@@ -310,115 +301,116 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
310301 return Promise . reject ( this . translate . instant ( 'core.errorsyncblocked' , { $a : this . componentTranslate } ) ) ;
311302 }
312303
304+ return this . addOngoingSync ( quiz . id , this . performSyncQuiz ( quiz , askPreflight , siteId ) , siteId ) ;
305+ }
306+
307+ /**
308+ * Perform the quiz sync.
309+ *
310+ * @param quiz Quiz.
311+ * @param askPreflight Whether we should ask for preflight data if needed.
312+ * @param siteId Site ID. If not defined, current site.
313+ * @return Promise resolved in success.
314+ */
315+ async performSyncQuiz ( quiz : any , askPreflight ?: boolean , siteId ?: string ) : Promise < AddonModQuizSyncResult > {
316+ siteId = siteId || this . sitesProvider . getCurrentSiteId ( ) ;
317+
318+ const warnings = [ ] ;
319+ const courseId = quiz . course ;
320+ const modOptions = {
321+ cmId : quiz . coursemodule ,
322+ readingStrategy : CoreSitesReadingStrategy . OnlyNetwork ,
323+ siteId,
324+ } ;
325+
313326 this . logger . debug ( 'Try to sync quiz ' + quiz . id + ' in site ' + siteId ) ;
314327
315328 // Sync offline logs.
316- syncPromise = this . logHelper . syncIfNeeded ( AddonModQuizProvider . COMPONENT , quiz . id , siteId ) . catch ( ( ) => {
317- // Ignore errors.
318- } ) . then ( ( ) => {
319- // Get all the offline attempts for the quiz.
320- return this . quizOfflineProvider . getQuizAttempts ( quiz . id , siteId ) ;
321- } ) . then ( ( attempts ) => {
322- // Should return 0 or 1 attempt.
323- if ( ! attempts . length ) {
324- return this . finishSync ( siteId , quiz , courseId , warnings ) ;
325- }
329+ await CoreUtils . instance . ignoreErrors ( this . logHelper . syncIfNeeded ( AddonModQuizProvider . COMPONENT , quiz . id , siteId ) ) ;
326330
327- const offlineAttempt = attempts . pop ( ) ;
331+ // Get all the offline attempts for the quiz. It should always be 0 or 1 attempt
332+ const offlineAttempts = await this . quizOfflineProvider . getQuizAttempts ( quiz . id , siteId ) ;
328333
329- // Now get the list of online attempts to make sure this attempt exists and isn't finished.
330- return this . quizProvider . getUserAttempts ( quiz . id , modOptions ) . then ( ( attempts ) => {
331- const lastAttemptId = attempts . length ? attempts [ attempts . length - 1 ] . id : undefined ;
332- let onlineAttempt ;
334+ if ( ! offlineAttempts . length ) {
335+ // Nothing to sync, finish.
336+ return this . finishSync ( siteId , quiz , courseId , warnings ) ;
337+ }
333338
334- // Search the attempt we retrieved from offline.
335- for ( const i in attempts ) {
336- const attempt = attempts [ i ] ;
339+ if ( ! this . appProvider . isOnline ( ) ) {
340+ // Cannot sync in offline.
341+ throw new Error ( this . translate . instant ( 'core.cannotconnect' ) ) ;
342+ }
337343
338- if ( attempt . id == offlineAttempt . id ) {
339- onlineAttempt = attempt ;
340- break ;
341- }
342- }
344+ const offlineAttempt = offlineAttempts . pop ( ) ;
343345
344- if ( ! onlineAttempt || this . quizProvider . isAttemptFinished ( onlineAttempt . state ) ) {
345- // Attempt not found or it's finished in online. Discard it.
346- warnings . push ( this . translate . instant ( 'addon.mod_quiz.warningattemptfinished' ) ) ;
346+ // Now get the list of online attempts to make sure this attempt exists and isn't finished.
347+ const onlineAttempts = await this . quizProvider . getUserAttempts ( quiz . id , modOptions ) ;
347348
348- return this . finishSync ( siteId , quiz , courseId , warnings , offlineAttempt . id , offlineAttempt , onlineAttempt ,
349- true ) ;
350- }
349+ const lastAttemptId = onlineAttempts . length ? onlineAttempts [ onlineAttempts . length - 1 ] . id : undefined ;
350+ const onlineAttempt = onlineAttempts . find ( ( attempt ) => {
351+ return attempt . id == offlineAttempt . id ;
352+ } ) ;
351353
352- // Get the data stored in offline.
353- return this . quizOfflineProvider . getAttemptAnswers ( offlineAttempt . id , siteId ) . then ( ( answersList ) => {
354+ if ( ! onlineAttempt || this . quizProvider . isAttemptFinished ( onlineAttempt . state ) ) {
355+ // Attempt not found or it's finished in online. Discard it.
356+ warnings . push ( this . translate . instant ( 'addon.mod_quiz.warningattemptfinished' ) ) ;
354357
355- if ( ! answersList . length ) {
356- // No answers stored, finish.
357- return this . finishSync ( siteId , quiz , courseId , warnings , lastAttemptId , offlineAttempt , onlineAttempt ,
358- true ) ;
359- }
358+ return this . finishSync ( siteId , quiz , courseId , warnings , offlineAttempt . id , offlineAttempt , onlineAttempt , true ) ;
359+ }
360360
361- const answers = this . questionProvider . convertAnswersArrayToObject ( answersList ) ,
362- offlineQuestions = this . quizOfflineProvider . classifyAnswersInQuestions ( answers ) ;
363- let finish ;
361+ // Get the data stored in offline.
362+ const answersList = await this . quizOfflineProvider . getAttemptAnswers ( offlineAttempt . id , siteId ) ;
364363
365- // We're going to need preflightData, get it.
366- return this . quizProvider . getQuizAccessInformation ( quiz . id , modOptions ) . then ( ( info ) => {
364+ if ( ! answersList . length ) {
365+ // No answers stored, finish.
366+ return this . finishSync ( siteId , quiz , courseId , warnings , lastAttemptId , offlineAttempt , onlineAttempt , true ) ;
367+ }
367368
368- return this . prefetchHandler . getPreflightData ( quiz , info , onlineAttempt , askPreflight ,
369- 'core.settings.synchronization' , siteId ) ;
370- } ) . then ( ( data ) => {
371- preflightData = data ;
369+ const offlineAnswers = this . questionProvider . convertAnswersArrayToObject ( answersList ) ;
370+ const offlineQuestions = this . quizOfflineProvider . classifyAnswersInQuestions ( offlineAnswers ) ;
372371
373- // Now get the online questions data .
374- const pages = this . quizProvider . getPagesFromLayoutAndQuestions ( onlineAttempt . layout , offlineQuestions ) ;
372+ // We're going to need preflightData, get it .
373+ const info = await this . quizProvider . getQuizAccessInformation ( quiz . id , modOptions ) ;
375374
376- return this . quizProvider . getAllQuestionsData ( quiz , onlineAttempt , preflightData , {
377- pages,
378- readingStrategy : CoreSitesReadingStrategy . OnlyNetwork ,
379- siteId,
380- } ) ;
381- } ) . then ( ( onlineQuestions ) => {
375+ const preflightData = await this . prefetchHandler . getPreflightData ( quiz , info , onlineAttempt , askPreflight ,
376+ 'core.settings.synchronization' , siteId ) ;
377+
378+ // Now get the online questions data.
379+ const pages = this . quizProvider . getPagesFromLayoutAndQuestions ( onlineAttempt . layout , offlineQuestions ) ;
380+
381+ const onlineQuestions = await this . quizProvider . getAllQuestionsData ( quiz , onlineAttempt , preflightData , {
382+ pages,
383+ readingStrategy : CoreSitesReadingStrategy . OnlyNetwork ,
384+ siteId,
385+ } ) ;
382386
383- // Validate questions, discarding the offline answers that can't be synchronized.
384- return this . validateQuestions ( onlineAttempt . id , onlineQuestions , offlineQuestions , siteId ) ;
385- } ) . then ( ( discardedData ) => {
387+ // Validate questions, discarding the offline answers that can't be synchronized.
388+ const discardedData = await this . validateQuestions ( onlineAttempt . id , onlineQuestions , offlineQuestions , siteId ) ;
386389
387- // Get the answers to send.
388- const answers = this . quizOfflineProvider . extractAnswersFromQuestions ( offlineQuestions ) ;
389- finish = offlineAttempt . finished && ! discardedData ;
390+ // Get the answers to send.
391+ const answers = this . quizOfflineProvider . extractAnswersFromQuestions ( offlineQuestions ) ;
392+ const finish = offlineAttempt . finished && ! discardedData ;
390393
391- if ( discardedData ) {
392- if ( offlineAttempt . finished ) {
393- warnings . push ( this . translate . instant ( 'addon.mod_quiz.warningdatadiscardedfromfinished' ) ) ;
394- } else {
395- warnings . push ( this . translate . instant ( 'addon.mod_quiz.warningdatadiscarded' ) ) ;
396- }
397- }
394+ if ( discardedData ) {
395+ if ( offlineAttempt . finished ) {
396+ warnings . push ( this . translate . instant ( 'addon.mod_quiz.warningdatadiscardedfromfinished' ) ) ;
397+ } else {
398+ warnings . push ( this . translate . instant ( 'addon.mod_quiz.warningdatadiscarded' ) ) ;
399+ }
400+ }
398401
399- return this . quizProvider . processAttempt ( quiz , onlineAttempt , answers , preflightData , finish , false , false ,
400- siteId ) ;
401- } ) . then ( ( ) => {
402-
403- // Answers sent, now set the current page if the attempt isn't finished.
404- if ( ! finish ) {
405- // Don't pass the quiz instance because we don't want to trigger a Firebase event in this case.
406- return this . quizProvider . logViewAttempt ( onlineAttempt . id , offlineAttempt . currentpage , preflightData ,
407- false , undefined , siteId ) . catch ( ( ) => {
408- // Ignore errors.
409- } ) ;
410- }
411- } ) . then ( ( ) => {
402+ // Send the answers.
403+ await this . quizProvider . processAttempt ( quiz , onlineAttempt , answers , preflightData , finish , false , false , siteId ) ;
412404
413- // Data sent. Finish the sync.
414- return this . finishSync ( siteId , quiz , courseId , warnings , lastAttemptId , offlineAttempt , onlineAttempt ,
415- true , true ) ;
416- } ) ;
417- } ) ;
418- } ) ;
419- } ) ;
405+ if ( ! finish ) {
406+ // Answers sent, now set the current page.
407+ // Don't pass the quiz instance because we don't want to trigger a Firebase event in this case.
408+ await CoreUtils . instance . ignoreErrors ( this . quizProvider . logViewAttempt ( onlineAttempt . id , offlineAttempt . currentpage ,
409+ preflightData , false , undefined , siteId ) ) ;
410+ }
420411
421- return this . addOngoingSync ( quiz . id , syncPromise , siteId ) ;
412+ // Data sent. Finish the sync.
413+ return this . finishSync ( siteId , quiz , courseId , warnings , lastAttemptId , offlineAttempt , onlineAttempt , true , true ) ;
422414 }
423415
424416 /**
0 commit comments