@@ -128,9 +128,22 @@ public InheritedThemeFileResult Resolve(string virtualPath)
128128 return null ;
129129 }
130130
131+ bool isExplicit = false ;
132+
131133 string requestedThemeName ;
132134 string relativePath ;
133- TokenizePath ( virtualPath , out requestedThemeName , out relativePath ) ;
135+ string query ;
136+
137+ virtualPath = TokenizePath ( virtualPath , out requestedThemeName , out relativePath , out query ) ;
138+
139+ Func < InheritedThemeFileResult > nullOrFile = ( ) =>
140+ {
141+ if ( isExplicit )
142+ {
143+ return new InheritedThemeFileResult { IsExplicit = true , OriginalVirtualPath = virtualPath } ;
144+ }
145+ return null ;
146+ } ;
134147
135148 ThemeManifest currentTheme ;
136149 var isAdmin = EngineContext . Current . Resolve < IWorkContext > ( ) . IsAdmin ; // ThemeHelper.IsAdminArea()
@@ -141,7 +154,7 @@ public InheritedThemeFileResult Resolve(string virtualPath)
141154 else
142155 {
143156 bool isLess = false ;
144- if ( ThemeHelper . IsStyleSheet ( virtualPath , out isLess ) )
157+ if ( ThemeHelper . IsStyleSheet ( relativePath , out isLess ) && isLess )
145158 {
146159 // special consideration for LESS files: they can be validated
147160 // in the backend. For validation, a "theme" query is appended
@@ -157,21 +170,36 @@ public InheritedThemeFileResult Resolve(string virtualPath)
157170 }
158171 }
159172 }
160-
161- currentTheme = ThemeHelper . ResolveCurrentTheme ( ) ;
173+
174+ if ( isLess && query != null && query . StartsWith ( "explicit" , StringComparison . OrdinalIgnoreCase ) )
175+ {
176+ // special case to support LESS @import declarations
177+ // within inherited LESS files. Snenario: an inheritor wishes to
178+ // include the same file from it's base theme (e.g. custom.less) just to tweak it
179+ // a bit for his child theme. Without the 'explicit' query the resolution starting point
180+ // for custom.less would be the CURRENT theme's folder, and NOT the requested one's,
181+ // which inevitably would result in a cyclic dependency.
182+ currentTheme = _themeRegistry . GetThemeManifest ( requestedThemeName ) ;
183+ isExplicit = true ;
184+ }
185+ else
186+ {
187+ currentTheme = ThemeHelper . ResolveCurrentTheme ( ) ;
188+ }
189+
162190 if ( currentTheme . BaseTheme == null )
163191 {
164192 // dont't bother resolving files: the current theme is not inherited.
165193 // Let the current VPP do the work.
166- return null ;
194+ return nullOrFile ( ) ;
167195 }
168196 }
169197
170198 if ( ! currentTheme . ThemeName . Equals ( requestedThemeName , StringComparison . OrdinalIgnoreCase ) )
171199 {
172200 if ( ! _themeRegistry . IsChildThemeOf ( currentTheme . ThemeName , requestedThemeName ) )
173201 {
174- return null ;
202+ return nullOrFile ( ) ;
175203 }
176204 }
177205
@@ -200,17 +228,33 @@ public InheritedThemeFileResult Resolve(string virtualPath)
200228 return null ;
201229 } ) ;
202230
231+ if ( result == null )
232+ {
233+ return nullOrFile ( ) ;
234+ }
235+
203236 return result ;
204237 }
205238
206- private void TokenizePath ( string virtualPath , out string themeName , out string relativePath )
239+ private string TokenizePath ( string virtualPath , out string themeName , out string relativePath , out string query )
207240 {
208241 themeName = null ;
209242 relativePath = null ;
243+ query = null ;
210244
211245 var unrooted = virtualPath . Substring ( ThemeHelper . ThemesBasePath . Length ) ; // strip "~/Themes/"
212246 themeName = unrooted . Substring ( 0 , unrooted . IndexOf ( '/' ) ) ;
213247 relativePath = unrooted . Substring ( themeName . Length + 1 ) ;
248+
249+ var idx = relativePath . IndexOf ( '?' ) ;
250+ if ( idx > 0 )
251+ {
252+ query = relativePath . Substring ( idx + 1 ) ;
253+ relativePath = relativePath . Substring ( 0 , idx ) ;
254+ }
255+
256+ // strip out query
257+ return "{0}{1}/{2}" . FormatCurrent ( ThemeHelper . ThemesBasePath , themeName , relativePath ) ;
214258 }
215259
216260 /// <summary>
@@ -293,6 +337,8 @@ public class InheritedThemeFileResult
293337 /// The name of the resulting theme where the file is actually located
294338 /// </summary>
295339 public string ResultThemeName { get ; set ; }
340+
341+ internal bool IsExplicit { get ; set ; }
296342 }
297343
298344}
0 commit comments