@@ -17,6 +17,7 @@ import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChange } from '@
1717import { CoreCourse } from '@features/course/services/course' ;
1818import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate' ;
1919import { CoreSites } from '@services/sites' ;
20+ import { CoreUrlUtils } from '@services/utils/url' ;
2021
2122const assetsPath = 'assets/img/' ;
2223const fallbackModName = 'external-tool' ;
@@ -54,12 +55,7 @@ export class CoreModIconComponent implements OnInit, OnChanges {
5455 async ngOnInit ( ) : Promise < void > {
5556 if ( ! this . modname && this . modicon ) {
5657 // Guess module from the icon url.
57- const matches = this . modicon . match ( '/theme/image.php/[^/]+/([^/]+)/[-0-9]*/' ) ;
58- this . modname = ( matches && matches [ 1 ] ) || '' ;
59-
60- if ( this . modname . startsWith ( 'mod_' ) ) {
61- this . modname = this . modname . substring ( 4 ) ;
62- }
58+ this . modname = this . getComponentNameFromIconUrl ( this . modicon ) ;
6359 }
6460
6561 this . modNameTranslated = CoreCourse . translateModuleName ( this . modname , this . fallbackTranslation ) ;
@@ -105,16 +101,15 @@ export class CoreModIconComponent implements OnInit, OnChanges {
105101 ! ! this . modname &&
106102 ! ! this . componentId &&
107103 ! this . isLocalUrl &&
108- ! this . icon . match ( '/theme/image.php/[^/]+/' + this . modname + '/[-0-9]*/' ) ;
104+ this . getComponentNameFromIconUrl ( this . icon ) != this . modname ;
109105
110- const iconIsShape = await CoreCourseModuleDelegate . moduleIconIsShape ( this . modname , this . icon ) ;
111- this . noFilter = iconIsShape === false ;
106+ this . noFilter = await this . getIconNoFilter ( ) ;
112107 }
113108
114109 /**
115110 * Icon to load on error.
116111 */
117- loadFallbackIcon ( ) : void {
112+ async loadFallbackIcon ( ) : Promise < void > {
118113 this . isLocalUrl = true ;
119114 const moduleName = ! this . modname || CoreCourse . CORE_MODULES . indexOf ( this . modname ) < 0
120115 ? fallbackModName
@@ -127,7 +122,75 @@ export class CoreModIconComponent implements OnInit, OnChanges {
127122 }
128123
129124 this . icon = path + moduleName + '.svg' ;
130- this . noFilter = false ;
125+ this . noFilter = await this . getIconNoFilter ( ) ;
126+ }
127+
128+ /**
129+ * Returns if the icon does not need to be filtered.
130+ *
131+ * @returns wether the icon does not need to be filtered.
132+ */
133+ protected async getIconNoFilter ( ) : Promise < boolean > {
134+ // Earlier 4.0, icons were never filtered.
135+ if ( this . legacyIcon ) {
136+ return true ;
137+ }
138+
139+ // No icon or local icon (not legacy), filter it.
140+ if ( ! this . icon || this . isLocalUrl ) {
141+ return false ;
142+ }
143+
144+ // If it's an Moodle Theme icon, check if filtericon is set and use it.
145+ if ( this . icon && CoreUrlUtils . isThemeImageUrl ( this . icon ) ) {
146+ const iconParams = CoreUrlUtils . extractUrlParams ( this . icon ) ;
147+ if ( iconParams [ 'filtericon' ] === '1' ) {
148+ return false ;
149+ }
150+
151+ // filtericon was introduced in 4.2 and backported to 4.1.3 and 4.0.8.
152+ if ( this . modname && ! CoreSites . getCurrentSite ( ) ?. isVersionGreaterEqualThan ( [ '4.0.8' , '4.1.3' , '4.2' ] ) ) {
153+ // If version is prior to that, check if the url is a module icon and filter it.
154+ if ( this . getComponentNameFromIconUrl ( this . icon ) === this . modname ) {
155+ return false ;
156+ }
157+ }
158+ }
159+
160+ // External icons, or non monologo, do not filter.
161+ return true ;
162+ }
163+
164+ /**
165+ * Guesses the mod name form the url.
166+ *
167+ * @param iconUrl Icon url.
168+ * @returns Guessed modname.
169+ */
170+ protected getComponentNameFromIconUrl ( iconUrl : string ) : string {
171+ if ( ! CoreUrlUtils . isThemeImageUrl ( this . icon ) ) {
172+ // Cannot be guessed.
173+ return '' ;
174+ }
175+
176+ const iconParams = CoreUrlUtils . extractUrlParams ( iconUrl ) ;
177+ let component = iconParams [ 'component' ] ;
178+
179+ if ( ! component ) {
180+ const matches = iconUrl . match ( '/theme/image.php/[^/]+/([^/]+)/[-0-9]*/' ) ;
181+ component = ( matches && matches [ 1 ] ) || '' ;
182+ }
183+
184+ // Some invalid components (others may be added later on).
185+ if ( component === 'core' || component === 'theme' ) {
186+ return '' ;
187+ }
188+
189+ if ( component . startsWith ( 'mod_' ) ) {
190+ component = component . substring ( 4 ) ;
191+ }
192+
193+ return component ;
131194 }
132195
133196}
0 commit comments