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));
            }
        }
Exemple #3
0
        /// <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()
                                                                    )
                                                                )));
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
            }
        }