public static IFileInfo GetContentFileInfo(this PathString path, IFileProvider fileProvider) { string rPath = (path == null || !path.HasValue || path.Value == "") ? "/" : path.Value; IFileInfo fileInfo = null; try { fileInfo = fileProvider.GetFileInfo(rPath); if (fileInfo == null) { fileInfo = new NotFoundFileInfo(rPath); } else if (fileInfo.Exists) { if (!fileInfo.IsDirectory) { return(fileInfo); } IDirectoryContents contents = fileProvider.GetDirectoryContents(rPath); IFileInfo page = DefaultPageNames.Select(p => contents.FirstOrDefault(c => String.Equals(p, c.Name, StringComparison.InvariantCultureIgnoreCase))) .FirstOrDefault(f => f != null); if (page != null) { fileInfo = page; } } } catch (Exception exception) { fileInfo = new GetFileError(rPath, exception); } return(fileInfo); }
public override DirectoryInfoBase GetDirectory(string name) { var isParentPath = name == ".."; if (!isParentPath) { IDirectoryContents contents = _fileProvider.GetDirectoryContents(FullName); IFileInfo item; return // string comparison should depend on environment or some kind of setting, // however it's irrelevant in this case as Matcher won't call this code (contents.Exists && (item = contents.FirstOrDefault(it => it.IsDirectory && it.Name.Equals(name, StringComparison.OrdinalIgnoreCase))) != null ? new GlobbingDirectoryInfo(_fileProvider, FullName, item.Name) : null); } else { return(new GlobbingDirectoryInfo(_fileProvider, _path, isParentPath)); } }
/// <summary> /// This will never return null nor contain any null entries /// </summary> public async Task <NonNullImmutableList <Post> > Get() { // The redirects set contains tuples From, To slugs (blank lines and those starting with a "#" are ignored, as are any that don't have any whitespace) const string redirectsFilename = "Redirects.txt"; var redirectsFile = _folder.FirstOrDefault(file => file.Name.Equals(redirectsFilename, StringComparison.OrdinalIgnoreCase)); IEnumerable <Tuple <string, string> > redirects; if (redirectsFile == null) { redirects = new List <Tuple <string, string> >(); } else { redirects = (await ReadFileContents(redirectsFile)) .Replace("\r\n", "\n") .Replace("\r", "\n") .Split('\n') .Select(entry => entry.Trim()) .Where(entry => (entry != "") && !entry.StartsWith("#") && entry.Any(c => char.IsWhiteSpace(c))) .Select(entry => new string(entry.Select(c => char.IsWhiteSpace(c) ? ' ' : c).ToArray())) .Select(entry => entry.Split(new[] { ' ' }, 2)) .Select(values => Tuple.Create(values[0], values[1])); } // The relatedPostRelationships set contains a map of Post Id to Ids of related Posts (in the order that they should appear) const string relatedPostsFilename = "RelatedPosts.txt"; var relatedPostsFile = _folder.FirstOrDefault(file => file.Name.Equals(relatedPostsFilename, StringComparison.OrdinalIgnoreCase)); var relatedPostRelationships = (relatedPostsFile == null) ? new Dictionary <int, ImmutableList <int> >() : await ReadRedirects(relatedPostsFile); // There is similar data in the AutoSuggestedRelatedPosts.txt file but the manually-created RelatedPosts.txt should take precedence in cases // where Post Ids appear in both const string autoSuggestedRelatedPostsFilename = "AutoSuggestedRelatedPosts.txt"; var autoSuggestedRelatedPostsFile = _folder.FirstOrDefault(file => file.Name.Equals(autoSuggestedRelatedPostsFilename, StringComparison.OrdinalIgnoreCase)); var autoSuggestedRelatedPostRelationships = (autoSuggestedRelatedPostsFile == null) ? new Dictionary <int, ImmutableList <int> >() : await ReadRedirects(autoSuggestedRelatedPostsFile); // We can use this functionality from the FullTextIndexer to generate the Post slug (it will replace accented characters, normalise whitespace, // remove punctuation and lower case the content - all we need to do then is replace spaces with hypens) var stringNormaliser = DefaultStringNormaliser.Instance; var posts = new List <Post>(); foreach (var file in _folder.Where(file => file.Name.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))) { if (file.Name.Equals(redirectsFilename, StringComparison.InvariantCultureIgnoreCase)) { continue; } var fileSummary = TryToGetFileSummaryEntry(file.Name); if (fileSummary != null) { var fileContents = await ReadFileContents(file); var title = TryToGetTitle(fileContents); if (title != null) { // 2014-09-17 DWR: Titles such as "C# State Machines" were being converted into "c-state-machines" which isn't as descriptive as // I'd like, "c-sharp-state-machines" is better. The replacement is done for "C#" and "F#" (a space is required after the // replacement content otherwise the "sharp" gets rolled into the next word) var slugBase = title.Replace("C#", "c sharp ").Replace("F#", "f sharp "); var slug = stringNormaliser.GetNormalisedString(slugBase).Replace(' ', '-'); var redirectsForPost = new NonNullOrEmptyStringList( redirects.Where(r => r.Item2 == slug).Select(r => r.Item1) ); // On this pass, set every tag's NumberOfPosts value to one since we don't have enough data to know better. After all of the // posts have been loaded, this can be fixed before the method terminates. if (!relatedPostRelationships.TryGetValue(fileSummary.Id, out var relatedPosts)) { relatedPosts = null; } if ((relatedPosts != null) || !autoSuggestedRelatedPostRelationships.TryGetValue(fileSummary.Id, out var autoSuggestedRelatedPosts)) { // Only check the autoSuggestedRelatedPostRelationships if there was no relatedPostRelationships entry - this allows for posts // to be specified as having no suggestions (manually-specified or auto-suggested) by having an entry in the manually-specified // file that has the post id but zero suggestions. autoSuggestedRelatedPosts = null; } posts.Add(new Post( fileSummary.Id, fileSummary.PostDate, file.LastModified.DateTime, slug, redirectsForPost, title, fileSummary.IsHighlight, fileContents, relatedPosts ?? new ImmutableList <int>(), autoSuggestedRelatedPosts ?? new ImmutableList <int>(), fileSummary.Tags.Select(tag => new TagSummary(tag, 1)).ToNonNullImmutableList() )); } } } var tagCounts = posts .SelectMany(post => post.Tags) .Select(tag => tag.Tag) .GroupBy(tag => tag, StringComparer.OrdinalIgnoreCase) .ToDictionary(groupedTag => groupedTag.Key, groupedTag => groupedTag.Count(), StringComparer.OrdinalIgnoreCase); return(new NonNullImmutableList <Post>(posts.Select(post => new Post( post.Id, post.Posted, post.LastModified, post.Slug, post.RedirectFromSlugs, post.Title, post.IsHighlight, post.MarkdownContent, post.RelatedPosts, post.AutoSuggestedRelatedPosts, post.Tags.Select(tag => new TagSummary(tag.Tag, tagCounts[tag.Tag])).ToNonNullImmutableList() ) ))); }
public static IList <IFileCultureInfo> FindFiles( string directory, string extension, ICultureExpression requestedCulture, IHostingEnvironment env) { string filePath; string targetName; string fileNameWithoutCulture; string nameNoExt; string culture; string filter; string relativeParent; int subLength; int lastIndex; string endsWithFilter = $".{extension}"; IEnumerable <IFileInfo> files; IEnumerable <IFileInfo> dirs; IFileProvider provider = env.ContentRootFileProvider; IDirectoryContents contents = provider.GetDirectoryContents(directory); List <IFileCultureInfo> result = new List <IFileCultureInfo>(); SortedSet <string> models = new SortedSet <string>(); if (requestedCulture.IsAllRegion) { // find by name // **.en.ext culture = requestedCulture.Language; filter = $".{culture}.{extension}"; files = contents.Where(x => !x.IsDirectory && x.Name.EndsWith(filter)); subLength = filter.Length; foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{directory}/{targetName}"; // Path.Combine(parentPath, fileName) fileNameWithoutCulture = targetName.Substring(0, targetName.Length - subLength); result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, requestedCulture)); models.Add(fileNameWithoutCulture); } // try find directory named with language // en/**.ext IFileInfo dir = contents.FirstOrDefault(x => x.IsDirectory && x.Name.Equals(culture)); if (dir != null) { relativeParent = $"{directory}/{culture}"; IDirectoryContents directoryContents = provider.GetDirectoryContents(relativeParent); files = directoryContents.Where(x => !x.IsDirectory && x.Name.EndsWith(endsWithFilter)); foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{relativeParent}/{targetName}";// Path.Combine(relatedParent, fileName) fileNameWithoutCulture = Path.GetFileNameWithoutExtension(targetName); if (!models.Contains(fileNameWithoutCulture)) { result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, requestedCulture)); models.Add(fileNameWithoutCulture); } } } // find the regions having the same language // **.en-**.ext filter = $@"\.{culture}-[a-zA-Z]{{2}}\.{extension}$"; Regex reg = new Regex(filter); files = contents.Where(x => !x.IsDirectory && reg.IsMatch(x.Name)); foreach (IFileInfo file in files) { targetName = file.Name; nameNoExt = Path.GetFileNameWithoutExtension(targetName); lastIndex = nameNoExt.LastIndexOf('.'); fileNameWithoutCulture = targetName.Substring(0, lastIndex); filePath = $"{directory}/{targetName}"; //Path.Combine(parentPath, fileName) culture = nameNoExt.Substring(lastIndex + 1); if (!models.Contains(fileNameWithoutCulture)) { result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, culture.ParseCultureExpression())); models.Add(fileNameWithoutCulture); } } // try find directory named with regions having the same language // en-**/**.ext filter = $"^{culture}-[a-zA-Z]{{2}}$"; reg = new Regex(filter); dirs = contents.Where(x => x.IsDirectory && reg.IsMatch(x.Name)); foreach (IFileInfo langDir in dirs) { culture = langDir.Name; ICultureExpression cultureExp = culture.ParseCultureExpression(); relativeParent = $"{directory}/{culture}"; //Path.Combine(parentPath, culture) IDirectoryContents directoryContents = provider.GetDirectoryContents(relativeParent); files = directoryContents.Where(x => !x.IsDirectory && x.Name.EndsWith(endsWithFilter)); foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{relativeParent}/{targetName}"; //Path.Combine(relatedParent, fileName) fileNameWithoutCulture = Path.GetFileNameWithoutExtension(targetName); if (!models.Contains(fileNameWithoutCulture)) { result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, cultureExp)); models.Add(fileNameWithoutCulture); } } } } else { // find by name // **.en-US.ext culture = requestedCulture.DisplayName; filter = $".{culture}.{extension}"; files = contents.Where(x => !x.IsDirectory && x.Name.EndsWith(filter)); subLength = filter.Length; foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{directory}/{targetName}"; //Path.Combine(parentPath, fileName) fileNameWithoutCulture = targetName.Substring(0, targetName.Length - subLength); result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, requestedCulture)); models.Add(fileNameWithoutCulture); } // try find directory named with culture name // en-US/**.ext dirs = contents.Where(x => x.IsDirectory && x.Name.Equals(culture)); foreach (IFileInfo langDir in dirs) { relativeParent = $"{directory}/{culture}"; //Path.Combine(parentPath, culture) IDirectoryContents directoryContents = provider.GetDirectoryContents(relativeParent); files = directoryContents.Where(x => !x.IsDirectory && x.Name.EndsWith(endsWithFilter)); foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{relativeParent}/{targetName}"; //Path.Combine(relatedParent, fileName) fileNameWithoutCulture = Path.GetFileNameWithoutExtension(targetName); if (!models.Contains(fileNameWithoutCulture)) { result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, requestedCulture)); models.Add(fileNameWithoutCulture); } } } // find the regions having the same language // **.en.ext culture = requestedCulture.Language; ICultureExpression cultureExp = culture.ParseCultureExpression(); filter = $".{culture}.{extension}"; files = contents.Where(x => !x.IsDirectory && x.Name.EndsWith(filter)); subLength = filter.Length; foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{directory}/{targetName}"; //Path.Combine(parentPath, fileName) fileNameWithoutCulture = targetName.Substring(0, targetName.Length - subLength); if (!models.Contains(fileNameWithoutCulture)) { result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, cultureExp)); models.Add(fileNameWithoutCulture); } } // try find directory named with the same language // en/**.ext relativeParent = $"{directory}/{culture}"; //Path.Combine(parentPath, culture) IFileInfo dir = contents.FirstOrDefault(x => x.IsDirectory && x.Name.Equals(culture)); if (dir != null) { IDirectoryContents directoryContents = provider.GetDirectoryContents(relativeParent); files = directoryContents.Where(x => !x.IsDirectory && x.Name.EndsWith(endsWithFilter)); foreach (IFileInfo file in files) { targetName = file.Name; filePath = $"{relativeParent}/{targetName}"; //Path.Combine(relatedParent, fileName) fileNameWithoutCulture = Path.GetFileNameWithoutExtension(targetName); if (!models.Contains(fileNameWithoutCulture)) { result.Add(new FileCultureInfo(filePath, targetName, fileNameWithoutCulture, extension, cultureExp)); models.Add(fileNameWithoutCulture); } } } } return(result); }
public override ViewEngineResult FindView(ActionContext actionContext, ViewResult viewResult) { string viewName = viewResult.ViewName; if (viewName == null) { viewName = GetActionName(actionContext); } if (viewName == null) { return(base.FindView(actionContext, viewResult)); } string controllerName; if (!actionContext.ActionDescriptor.RouteValues.TryGetValue(ControllerNameKey, out controllerName) || string.IsNullOrEmpty(controllerName)) { controllerName = ""; } string basePath = Path.Combine("Views", controllerName, viewName); IServiceProvider services = actionContext.HttpContext.RequestServices; CultureContext cultureContext = services.GetRequiredService <CultureContext>(); CultureExpression cultureExpression = cultureContext.Culture; string requestedLanguage = cultureExpression.Language; string lang = requestedLanguage; string nameResult; if (!cultureExpression.IsAllRegion && IsViewFileExisits(lang, out nameResult)) { // exact match viewResult.ViewName = nameResult; viewResult.ViewData["Language"] = new LanguageRequestResult(lang, lang, true); return(base.FindView(actionContext, viewResult)); } lang = cultureExpression.LanguageName; if (IsViewFileExisits(lang, out nameResult)) { // language name match viewResult.ViewName = nameResult; viewResult.ViewData["Language"] = new LanguageRequestResult(requestedLanguage, lang, true); return(base.FindView(actionContext, viewResult)); } else { // find the first availble region of one language IDirectoryContents directoryContents = env.ContentRootFileProvider.GetDirectoryContents(Path.Combine("Views", controllerName)); string startsWithFilter = $"{viewName}.{lang}"; IFileInfo file = directoryContents.FirstOrDefault(x => x.Name.StartsWith(startsWithFilter) && x.Name.EndsWith(".cshtml")); if (file != null) { string cultureName = file.Name.Substring(viewName.Length + 1); cultureName.Substring(0, cultureName.Length - 7); nameResult = file.Name.Substring(0, file.Name.Length - 7); if (CultureExpression.TryParse(cultureName, out CultureExpression exp)) { viewResult.ViewData["Language"] = new LanguageRequestResult(requestedLanguage, exp.Language, true); } else { viewResult.ViewData["Language"] = new LanguageRequestResult(requestedLanguage, null, false); } viewResult.ViewName = nameResult; return(base.FindView(actionContext, viewResult)); } } CultureExpression defaultLanguage = cultureContext.Options.DefaultLanguage; lang = defaultLanguage.Language; if (IsViewFileExisits(lang, out nameResult)) { // default language match viewResult.ViewName = nameResult; viewResult.ViewData["Language"] = new LanguageRequestResult(requestedLanguage, lang, false); return(base.FindView(actionContext, viewResult)); } lang = defaultLanguage.LanguageName; if (IsViewFileExisits(lang, out nameResult)) { // default language name match viewResult.ViewName = nameResult; viewResult.ViewData["Language"] = new LanguageRequestResult(requestedLanguage, lang, false); return(base.FindView(actionContext, viewResult)); } // default file match viewResult.ViewName = viewName; viewResult.ViewData["Language"] = new LanguageRequestResult(requestedLanguage, null, false); return(base.FindView(actionContext, viewResult)); bool IsViewFileExisits(string language, out string viewNameaResult) { string pathWithLang = $"{basePath}.{lang}.cshtml"; if (env.ContentRootFileProvider.GetFileInfo(pathWithLang).Exists) { viewNameaResult = viewName + "." + lang; return(true); } viewNameaResult = null; return(false); } }