Skip to content

Commit ea08c78

Browse files
committed
MOBILE-4653 chore: Remove direct circular dependancies on addons
1 parent 2af5ddf commit ea08c78

File tree

18 files changed

+244
-199
lines changed

18 files changed

+244
-199
lines changed

.github/workflows/testing.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
cat circular-dependencies
7070
lines=$(cat circular-dependencies | wc -l)
7171
echo "Total circular dependencies: $lines"
72-
test $lines -eq 95
72+
test $lines -eq 85
7373
- name: JavaScript code compatibility
7474
run: |
7575
npx check-es-compat www/*.js --polyfills="\{Array,String,TypedArray\}.prototype.at,Object.hasOwn"

src/addons/mod/choice/components/index/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import {
3333
AddonModChoiceSync,
3434
AddonModChoiceSyncResult,
3535
} from '../../services/choice-sync';
36-
import { AddonModChoicePrefetchHandler } from '../../services/handlers/prefetch';
3736
import {
3837
ADDON_MOD_CHOICE_AUTO_SYNCED,
3938
ADDON_MOD_CHOICE_COMPONENT,
@@ -463,7 +462,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
463462

464463
try {
465464
// The choice is downloaded, update the data.
466-
await AddonModChoiceSync.prefetchAfterUpdate(AddonModChoicePrefetchHandler.instance, this.module, this.courseId);
465+
await AddonModChoiceSync.prefetchModuleAfterUpdate(this.module, this.courseId);
467466

468467
// Update the view.
469468
this.showLoadingAndFetch(false, false);

src/addons/mod/choice/services/choice-sync.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import { makeSingleton } from '@singletons';
2525
import { CoreEvents } from '@singletons/events';
2626
import { AddonModChoice } from './choice';
2727
import { AddonModChoiceOffline } from './choice-offline';
28-
import { AddonModChoicePrefetchHandler } from './handlers/prefetch';
2928
import { ADDON_MOD_CHOICE_AUTO_SYNCED, ADDON_MOD_CHOICE_COMPONENT } from '../constants';
3029
import { CorePromiseUtils } from '@singletons/promise-utils';
3130

@@ -213,7 +212,7 @@ export class AddonModChoiceSyncProvider extends CoreCourseActivitySyncBaseProvid
213212
try {
214213
const module = await CoreCourse.getModuleBasicInfoByInstance(choiceId, 'choice', { siteId });
215214

216-
await this.prefetchAfterUpdate(AddonModChoicePrefetchHandler.instance, module, courseId, undefined, siteId);
215+
await this.prefetchModuleAfterUpdate(module, courseId, undefined, siteId);
217216
} catch {
218217
// Ignore errors.
219218
}

src/addons/mod/feedback/components/index/index.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import {
3737
AddonModFeedbackSync,
3838
AddonModFeedbackSyncResult,
3939
} from '../../services/feedback-sync';
40-
import { AddonModFeedbackPrefetchHandler } from '../../services/handlers/prefetch';
4140
import {
4241
ADDON_MOD_FEEDBACK_AUTO_SYNCED,
4342
ADDON_MOD_FEEDBACK_COMPONENT,
@@ -117,8 +116,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
117116

118117
// Prefetch data if needed.
119118
if (!data.offline && this.isPrefetched()) {
120-
await CorePromiseUtils.ignoreErrors(AddonModFeedbackSync.prefetchAfterUpdate(
121-
AddonModFeedbackPrefetchHandler.instance,
119+
await CorePromiseUtils.ignoreErrors(AddonModFeedbackSync.prefetchModuleAfterUpdate(
122120
this.module,
123121
this.courseId,
124122
));

src/addons/mod/feedback/services/feedback-sync.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import { makeSingleton, Translate } from '@singletons';
2626
import { CoreEvents } from '@singletons/events';
2727
import { AddonModFeedback, AddonModFeedbackWSFeedback } from './feedback';
2828
import { AddonModFeedbackOffline, AddonModFeedbackOfflineResponse } from './feedback-offline';
29-
import { AddonModFeedbackPrefetchHandler, AddonModFeedbackPrefetchHandlerService } from './handlers/prefetch';
3029
import { ADDON_MOD_FEEDBACK_AUTO_SYNCED, ADDON_MOD_FEEDBACK_COMPONENT } from '../constants';
3130
import { CorePromiseUtils } from '@singletons/promise-utils';
3231

@@ -45,16 +44,15 @@ export class AddonModFeedbackSyncProvider extends CoreCourseActivitySyncBaseProv
4544
/**
4645
* @inheritdoc
4746
*/
48-
prefetchAfterUpdate(
49-
prefetchHandler: AddonModFeedbackPrefetchHandlerService,
47+
prefetchModuleAfterUpdate(
5048
module: CoreCourseAnyModuleData,
5149
courseId: number,
5250
regex?: RegExp,
5351
siteId?: string,
5452
): Promise<boolean> {
5553
regex = regex || /^.*files$|^timers/;
5654

57-
return super.prefetchAfterUpdate(prefetchHandler, module, courseId, regex, siteId);
55+
return super.prefetchModuleAfterUpdate(module, courseId, regex, siteId);
5856
}
5957

6058
/**
@@ -225,7 +223,7 @@ export class AddonModFeedbackSyncProvider extends CoreCourseActivitySyncBaseProv
225223
try {
226224
const module = await CoreCourse.getModuleBasicInfoByInstance(feedbackId, 'feedback', { siteId });
227225

228-
await this.prefetchAfterUpdate(AddonModFeedbackPrefetchHandler.instance, module, courseId, undefined, siteId);
226+
await this.prefetchModuleAfterUpdate(module, courseId, undefined, siteId);
229227
} catch {
230228
// Ignore errors.
231229
}

src/addons/mod/lesson/components/index/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
681681

682682
if (!result.updated && this.dataSent && this.isPrefetched()) {
683683
// The user sent data to server, but not in the sync process. Check if we need to fetch data.
684-
await CorePromiseUtils.ignoreErrors(AddonModLessonSync.prefetchAfterUpdate(
685-
AddonModLessonPrefetchHandler.instance,
684+
await CorePromiseUtils.ignoreErrors(AddonModLessonSync.prefetchModuleAfterUpdate(
686685
this.module,
687686
this.courseId,
688687
));

src/addons/mod/lesson/services/handlers/prefetch.ts

+3-110
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
} from '../lesson';
3333
import { AddonModLessonSync, AddonModLessonSyncResult } from '../lesson-sync';
3434
import { ADDON_MOD_LESSON_COMPONENT, AddonModLessonJumpTo, AddonModLessonPageSubtype } from '../../constants';
35-
import { CorePrompts } from '@services/overlays/prompts';
35+
import { AddonModLessonHelper } from '../lesson-helper';
3636

3737
/**
3838
* Handler to prefetch lessons.
@@ -60,7 +60,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
6060
let lesson = await AddonModLesson.getLesson(courseId, module.id, { siteId });
6161

6262
// Get the lesson password if it's needed.
63-
const passwordData = await this.getLessonPassword(lesson.id, {
63+
const passwordData = await AddonModLessonHelper.getLessonPassword(lesson.id, {
6464
readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK,
6565
askPassword: single,
6666
siteId,
@@ -88,64 +88,6 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
8888
return result;
8989
}
9090

91-
/**
92-
* Get the lesson password if needed. If not stored, it can ask the user to enter it.
93-
*
94-
* @param lessonId Lesson ID.
95-
* @param options Other options.
96-
* @returns Promise resolved when done.
97-
*/
98-
async getLessonPassword(
99-
lessonId: number,
100-
options: AddonModLessonGetPasswordOptions = {},
101-
): Promise<AddonModLessonGetPasswordResult> {
102-
103-
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
104-
105-
// Get access information to check if password is needed.
106-
const accessInfo = await AddonModLesson.getAccessInformation(lessonId, options);
107-
108-
if (!accessInfo.preventaccessreasons.length) {
109-
// Password not needed.
110-
return { accessInfo };
111-
}
112-
113-
const passwordNeeded = accessInfo.preventaccessreasons.length == 1 &&
114-
AddonModLesson.isPasswordProtected(accessInfo);
115-
116-
if (!passwordNeeded) {
117-
// Lesson cannot be played, reject.
118-
throw new CoreError(accessInfo.preventaccessreasons[0].message);
119-
}
120-
121-
// The lesson requires a password. Check if there is one in DB.
122-
let password = await CorePromiseUtils.ignoreErrors(AddonModLesson.getStoredPassword(lessonId));
123-
124-
if (password) {
125-
try {
126-
return await this.validatePassword(lessonId, accessInfo, password, options);
127-
} catch {
128-
// Error validating it.
129-
}
130-
}
131-
132-
// Ask for the password if allowed.
133-
if (!options.askPassword) {
134-
// Cannot ask for password, reject.
135-
throw new CoreError(accessInfo.preventaccessreasons[0].message);
136-
}
137-
138-
// Create and show the modal.
139-
const response = await CorePrompts.promptPassword({
140-
title: 'addon.mod_lesson.enterpassword',
141-
placeholder: 'core.login.password',
142-
submit: 'addon.mod_lesson.continue',
143-
});
144-
password = response.password;
145-
146-
return this.validatePassword(lessonId, accessInfo, password, options);
147-
}
148-
14991
/**
15092
* Invalidate the prefetched content.
15193
*
@@ -241,7 +183,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
241183
let lesson = await AddonModLesson.getLesson(courseId, module.id, commonOptions);
242184

243185
// Get the lesson password if it's needed.
244-
const passwordData = await this.getLessonPassword(lesson.id, {
186+
const passwordData = await AddonModLessonHelper.getLessonPassword(lesson.id, {
245187
readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK,
246188
askPassword: single,
247189
siteId,
@@ -477,39 +419,6 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
477419
}));
478420
}
479421

480-
/**
481-
* Validate the password.
482-
*
483-
* @param lessonId Lesson ID.
484-
* @param accessInfo Lesson access info.
485-
* @param password Password to check.
486-
* @param options Other options.
487-
* @returns Promise resolved when done.
488-
*/
489-
protected async validatePassword(
490-
lessonId: number,
491-
accessInfo: AddonModLessonGetAccessInformationWSResponse,
492-
password: string,
493-
options: CoreCourseCommonModWSOptions = {},
494-
): Promise<AddonModLessonGetPasswordResult> {
495-
496-
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
497-
498-
const lesson = await AddonModLesson.getLessonWithPassword(lessonId, {
499-
password,
500-
...options, // Include all options.
501-
});
502-
503-
// Password is ok, store it and return the data.
504-
await AddonModLesson.storePassword(lesson.id, password, options.siteId);
505-
506-
return {
507-
password,
508-
lesson,
509-
accessInfo,
510-
};
511-
}
512-
513422
/**
514423
* Sync a module.
515424
*
@@ -525,19 +434,3 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
525434
}
526435

527436
export const AddonModLessonPrefetchHandler = makeSingleton(AddonModLessonPrefetchHandlerService);
528-
529-
/**
530-
* Options to pass to get lesson password.
531-
*/
532-
export type AddonModLessonGetPasswordOptions = CoreCourseCommonModWSOptions & {
533-
askPassword?: boolean; // True if we should ask for password if needed, false otherwise.
534-
};
535-
536-
/**
537-
* Result of getLessonPassword.
538-
*/
539-
export type AddonModLessonGetPasswordResult = {
540-
password?: string;
541-
lesson?: AddonModLessonLessonWSData;
542-
accessInfo: AddonModLessonGetAccessInformationWSResponse;
543-
};

src/addons/mod/lesson/services/lesson-helper.ts

+114
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ import { makeSingleton, Translate } from '@singletons';
2323
import {
2424
AddonModLesson,
2525
AddonModLessonAttemptsOverviewsAttemptWSData,
26+
AddonModLessonGetAccessInformationWSResponse,
2627
AddonModLessonGetPageDataWSResponse,
28+
AddonModLessonLessonWSData,
2729
} from './lesson';
2830
import { CoreTime } from '@singletons/time';
2931
import { CoreUtils } from '@singletons/utils';
3032
import { AddonModLessonPageSubtype } from '../constants';
3133
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
34+
import { CoreError } from '@classes/errors/error';
35+
import { CorePrompts } from '@services/overlays/prompts';
36+
import { CoreSites } from '@services/sites';
37+
import { CorePromiseUtils } from '@singletons/promise-utils';
38+
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
3239

3340
/**
3441
* Helper service that provides some features for quiz.
@@ -597,6 +604,97 @@ export class AddonModLessonHelperProvider {
597604
return element.innerHTML.trim();
598605
}
599606

607+
/**
608+
* Get the lesson password if needed. If not stored, it can ask the user to enter it.
609+
*
610+
* @param lessonId Lesson ID.
611+
* @param options Other options.
612+
* @returns Promise resolved when done.
613+
*/
614+
async getLessonPassword(
615+
lessonId: number,
616+
options: AddonModLessonGetPasswordOptions = {},
617+
): Promise<AddonModLessonGetPasswordResult> {
618+
619+
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
620+
621+
// Get access information to check if password is needed.
622+
const accessInfo = await AddonModLesson.getAccessInformation(lessonId, options);
623+
624+
if (!accessInfo.preventaccessreasons.length) {
625+
// Password not needed.
626+
return { accessInfo };
627+
}
628+
629+
const passwordNeeded = accessInfo.preventaccessreasons.length == 1 &&
630+
AddonModLesson.isPasswordProtected(accessInfo);
631+
632+
if (!passwordNeeded) {
633+
// Lesson cannot be played, reject.
634+
throw new CoreError(accessInfo.preventaccessreasons[0].message);
635+
}
636+
637+
// The lesson requires a password. Check if there is one in DB.
638+
let password = await CorePromiseUtils.ignoreErrors(AddonModLesson.getStoredPassword(lessonId));
639+
640+
if (password) {
641+
try {
642+
return await this.validatePassword(lessonId, accessInfo, password, options);
643+
} catch {
644+
// Error validating it.
645+
}
646+
}
647+
648+
// Ask for the password if allowed.
649+
if (!options.askPassword) {
650+
// Cannot ask for password, reject.
651+
throw new CoreError(accessInfo.preventaccessreasons[0].message);
652+
}
653+
654+
// Create and show the modal.
655+
const response = await CorePrompts.promptPassword({
656+
title: 'addon.mod_lesson.enterpassword',
657+
placeholder: 'core.login.password',
658+
submit: 'addon.mod_lesson.continue',
659+
});
660+
password = response.password;
661+
662+
return this.validatePassword(lessonId, accessInfo, password, options);
663+
}
664+
665+
/**
666+
* Validate the password.
667+
*
668+
* @param lessonId Lesson ID.
669+
* @param accessInfo Lesson access info.
670+
* @param password Password to check.
671+
* @param options Other options.
672+
* @returns Promise resolved when done.
673+
*/
674+
protected async validatePassword(
675+
lessonId: number,
676+
accessInfo: AddonModLessonGetAccessInformationWSResponse,
677+
password: string,
678+
options: CoreCourseCommonModWSOptions = {},
679+
): Promise<AddonModLessonGetPasswordResult> {
680+
681+
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
682+
683+
const lesson = await AddonModLesson.getLessonWithPassword(lessonId, {
684+
password,
685+
...options, // Include all options.
686+
});
687+
688+
// Password is ok, store it and return the data.
689+
await AddonModLesson.storePassword(lesson.id, password, options.siteId);
690+
691+
return {
692+
password,
693+
lesson,
694+
accessInfo,
695+
};
696+
}
697+
600698
}
601699
export const AddonModLessonHelper = makeSingleton(AddonModLessonHelperProvider);
602700

@@ -749,3 +847,19 @@ export type AddonModLessonActivityLink = {
749847
label: string;
750848
href: string;
751849
};
850+
851+
/**
852+
* Options to pass to get lesson password.
853+
*/
854+
export type AddonModLessonGetPasswordOptions = CoreCourseCommonModWSOptions & {
855+
askPassword?: boolean; // True if we should ask for password if needed, false otherwise.
856+
};
857+
858+
/**
859+
* Result of getLessonPassword.
860+
*/
861+
export type AddonModLessonGetPasswordResult = {
862+
password?: string;
863+
lesson?: AddonModLessonLessonWSData;
864+
accessInfo: AddonModLessonGetAccessInformationWSResponse;
865+
};

0 commit comments

Comments
 (0)