MOBILE-3903 enrol: Check guest first for course/view links
This commit is contained in:
		
							parent
							
								
									2de6c75f2a
								
							
						
					
					
						commit
						432f9b03ec
					
				@ -90,7 +90,7 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
 | 
			
		||||
 | 
			
		||||
                        return;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        this.actionEnrol(courseId, url, pageParams).catch(() => {
 | 
			
		||||
                        this.actionOpen(courseId, url, pageParams).catch(() => {
 | 
			
		||||
                            // Ignore errors.
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
@ -124,14 +124,14 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Action to perform when an enrol link is clicked.
 | 
			
		||||
     * Try to open the course, asking the user to enrol if needed.
 | 
			
		||||
     *
 | 
			
		||||
     * @param courseId Course ID.
 | 
			
		||||
     * @param url Treated URL.
 | 
			
		||||
     * @param pageParams Params to send to the new page.
 | 
			
		||||
     * @return Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    protected async actionEnrol(courseId: number, url: string, pageParams: Params): Promise<void> {
 | 
			
		||||
    protected async actionOpen(courseId: number, url: string, pageParams: Params): Promise<void> {
 | 
			
		||||
        const modal = await CoreDomUtils.showModalLoading();
 | 
			
		||||
        let course: CoreCourseAnyCourseData | { id: number } | undefined;
 | 
			
		||||
 | 
			
		||||
@ -167,95 +167,102 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
 | 
			
		||||
     * @param modal Modal, to dismiss when needed.
 | 
			
		||||
     * @return The course after self enrolling or undefined if the user has access but is not enrolled.
 | 
			
		||||
     */
 | 
			
		||||
    protected checkSelfUserCanSelfEnrolOrAccess(
 | 
			
		||||
    protected async checkSelfUserCanSelfEnrolOrAccess(
 | 
			
		||||
        courseId: number,
 | 
			
		||||
        url: string,
 | 
			
		||||
        modal: CoreIonLoadingElement,
 | 
			
		||||
    ): Promise<CoreEnrolledCourseData | undefined> {
 | 
			
		||||
        // User is not enrolled in the course. Check if can self enrol.
 | 
			
		||||
        return this.canSelfEnrol(courseId).then(async () => {
 | 
			
		||||
            modal.dismiss();
 | 
			
		||||
        const isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
 | 
			
		||||
 | 
			
		||||
            const isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
 | 
			
		||||
        if (!isEnrolUrl) {
 | 
			
		||||
            // Not an enrol URL, check if the user can access the course (e.g. guest access).
 | 
			
		||||
            const canAccess = await this.canAccess(courseId);
 | 
			
		||||
            if (canAccess) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // The user can self enrol. If it's not a enrolment URL we'll ask for confirmation.
 | 
			
		||||
            if (!isEnrolUrl) {
 | 
			
		||||
                try {
 | 
			
		||||
                    await CoreDomUtils.showConfirm(Translate.instant('core.courses.confirmselfenrol'));
 | 
			
		||||
                } catch {
 | 
			
		||||
                    // User cancelled. Check if the user can view the course contents (guest access or similar).
 | 
			
		||||
                    await CoreCourse.getSections(courseId, false, true);
 | 
			
		||||
        // User cannot access the course or it's an enrol URL. Check if can self enrol.
 | 
			
		||||
        const canSelfEnrol = await this.canSelfEnrol(courseId);
 | 
			
		||||
 | 
			
		||||
        if (!canSelfEnrol) {
 | 
			
		||||
            if (isEnrolUrl) {
 | 
			
		||||
                // Cannot self enrol, check if the user can access the course (e.g. guest access).
 | 
			
		||||
                const canAccess = await this.canAccess(courseId);
 | 
			
		||||
                if (canAccess) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Enrol URL or user confirmed.
 | 
			
		||||
            try {
 | 
			
		||||
                return this.selfEnrol(courseId);
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                if (error) {
 | 
			
		||||
                    CoreDomUtils.showErrorModal(error);
 | 
			
		||||
                }
 | 
			
		||||
            // Cannot self enrol and cannot access. Show error and allow the user to open the link in browser.
 | 
			
		||||
            modal.dismiss();
 | 
			
		||||
            const notEnrolledMessage = Translate.instant('core.courses.notenroled');
 | 
			
		||||
            const body = CoreTextUtils.buildSeveralParagraphsMessage(
 | 
			
		||||
                [notEnrolledMessage, Translate.instant('core.confirmopeninbrowser')],
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
                throw error;
 | 
			
		||||
            }
 | 
			
		||||
        }, async (error) => {
 | 
			
		||||
            // Can't self enrol. Check if the user can view the course contents (guest access or similar).
 | 
			
		||||
            try {
 | 
			
		||||
                await CoreCourse.getSections(courseId, false, true);
 | 
			
		||||
                await CoreDomUtils.showConfirm(body);
 | 
			
		||||
 | 
			
		||||
                CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(url, undefined, { showBrowserWarning: false });
 | 
			
		||||
            } catch {
 | 
			
		||||
                // Error. Show error message and allow the user to open the link in browser.
 | 
			
		||||
                modal.dismiss();
 | 
			
		||||
                // User cancelled.
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
                if (error) {
 | 
			
		||||
                    error = CoreTextUtils.getErrorMessageFromError(error) || error;
 | 
			
		||||
                }
 | 
			
		||||
                if (!error) {
 | 
			
		||||
                    error = Translate.instant('core.courses.notenroled');
 | 
			
		||||
                }
 | 
			
		||||
            throw new CoreError(notEnrolledMessage);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                const body = CoreTextUtils.buildSeveralParagraphsMessage(
 | 
			
		||||
                    [error, Translate.instant('core.confirmopeninbrowser')],
 | 
			
		||||
                );
 | 
			
		||||
        // The user can self enrol. If it's not a enrolment URL we'll ask for confirmation.
 | 
			
		||||
        modal.dismiss();
 | 
			
		||||
 | 
			
		||||
                try {
 | 
			
		||||
                    await CoreDomUtils.showConfirm(body);
 | 
			
		||||
        if (!isEnrolUrl) {
 | 
			
		||||
            await CoreDomUtils.showConfirm(Translate.instant('core.courses.confirmselfenrol'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                    CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(url, undefined, { showBrowserWarning: false });
 | 
			
		||||
                } catch {
 | 
			
		||||
                    // User cancelled.
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                throw error;
 | 
			
		||||
        try {
 | 
			
		||||
            return await this.selfEnrol(courseId);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            if (error) {
 | 
			
		||||
                CoreDomUtils.showErrorModal(error);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return undefined;
 | 
			
		||||
        });
 | 
			
		||||
            throw error;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if user can access the course.
 | 
			
		||||
     *
 | 
			
		||||
     * @param courseId Course ID.
 | 
			
		||||
     * @return Promise resolved with boolean: whether user can access the course.
 | 
			
		||||
     */
 | 
			
		||||
    protected canAccess(courseId: number): Promise<boolean> {
 | 
			
		||||
        return CoreUtils.promiseWorks(CoreCourse.getSections(courseId, false, true));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if a user can be "automatically" self enrolled in a course.
 | 
			
		||||
     *
 | 
			
		||||
     * @param courseId Course ID.
 | 
			
		||||
     * @return Promise resolved if user can be enrolled in a course, rejected otherwise.
 | 
			
		||||
     * @return Promise resolved with boolean: whether the user can be enrolled in a course.
 | 
			
		||||
     */
 | 
			
		||||
    protected async canSelfEnrol(courseId: number): Promise<void> {
 | 
			
		||||
        // Check that the course has self enrolment enabled.
 | 
			
		||||
    protected async canSelfEnrol(courseId: number): Promise<boolean> {
 | 
			
		||||
        try {
 | 
			
		||||
            // Check that the course has self enrolment enabled.
 | 
			
		||||
            const methods = await CoreCourses.getCourseEnrolmentMethods(courseId);
 | 
			
		||||
 | 
			
		||||
        const methods = await CoreCourses.getCourseEnrolmentMethods(courseId);
 | 
			
		||||
        let isSelfEnrolEnabled = false;
 | 
			
		||||
        let instances = 0;
 | 
			
		||||
        methods.forEach((method) => {
 | 
			
		||||
            if (method.type == 'self' && method.status) {
 | 
			
		||||
                isSelfEnrolEnabled = true;
 | 
			
		||||
                instances++;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
            let isSelfEnrolEnabled = false;
 | 
			
		||||
            let instances = 0;
 | 
			
		||||
            methods.forEach((method) => {
 | 
			
		||||
                if (method.type == 'self' && method.status) {
 | 
			
		||||
                    isSelfEnrolEnabled = true;
 | 
			
		||||
                    instances++;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        if (!isSelfEnrolEnabled || instances != 1) {
 | 
			
		||||
            // Self enrol not enabled or more than one instance.
 | 
			
		||||
            throw new CoreError('Self enrol not enabled in course');
 | 
			
		||||
            return isSelfEnrolEnabled && instances === 1;
 | 
			
		||||
        } catch {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -272,12 +279,9 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
 | 
			
		||||
        try {
 | 
			
		||||
            await CoreCourses.selfEnrol(courseId, password);
 | 
			
		||||
 | 
			
		||||
            // Success self enrolling the user, invalidate the courses list.
 | 
			
		||||
            await CoreUtils.ignoreErrors(CoreCourses.invalidateUserCourses());
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                // Sometimes the list of enrolled courses takes a while to be updated. Wait for it.
 | 
			
		||||
                return this.waitForEnrolled(courseId, true);
 | 
			
		||||
                return await this.waitForEnrolled(courseId, true);
 | 
			
		||||
            } finally {
 | 
			
		||||
                modal.dismiss();
 | 
			
		||||
            }
 | 
			
		||||
@ -297,7 +301,7 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
 | 
			
		||||
 | 
			
		||||
                password = await CoreDomUtils.showPrompt(body, title, placeholder);
 | 
			
		||||
 | 
			
		||||
                return this.selfEnrol(courseId, password);
 | 
			
		||||
                await this.selfEnrol(courseId, password);
 | 
			
		||||
            } else {
 | 
			
		||||
                throw error;
 | 
			
		||||
            }
 | 
			
		||||
@ -319,21 +323,17 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
 | 
			
		||||
        // Check if user is enrolled in the course.
 | 
			
		||||
        await CoreUtils.ignoreErrors(CoreCourses.invalidateUserCourses());
 | 
			
		||||
        try {
 | 
			
		||||
            return CoreCourses.getUserCourse(courseId);
 | 
			
		||||
            return await CoreCourses.getUserCourse(courseId);
 | 
			
		||||
        } catch {
 | 
			
		||||
 | 
			
		||||
            // Not enrolled, wait a bit and try again.
 | 
			
		||||
            if (Date.now() - this.waitStart > 60000) {
 | 
			
		||||
                // Max time reached, stop.
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new Promise((resolve, reject): void => {
 | 
			
		||||
                setTimeout(() => {
 | 
			
		||||
                    this.waitForEnrolled(courseId)
 | 
			
		||||
                        .then(resolve).catch(reject);
 | 
			
		||||
                }, 5000);
 | 
			
		||||
            });
 | 
			
		||||
            await CoreUtils.wait(5000);
 | 
			
		||||
 | 
			
		||||
            return await this.waitForEnrolled(courseId);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user