private async Task <ICollection <MappedPageBlock> > ToBlockMappingDataAsync( IEnumerable <IEntityVersionPageBlock> entityBlocks, IEnumerable <PageBlockTypeSummary> blockTypes, PublishStatusQuery workflowStatus ) { var mappedBlocks = new List <MappedPageBlock>(); foreach (var group in entityBlocks.GroupBy(m => m.PageBlockTypeId)) { var blockType = blockTypes.SingleOrDefault(t => t.PageBlockTypeId == group.Key); var mapperOutput = await _pageVersionBlockModelMapper.MapDisplayModelAsync(blockType.FileName, group, workflowStatus); foreach (var block in group) { var mappedBlock = new MappedPageBlock() { PageBlock = block, BlockType = blockType, DisplayModel = mapperOutput.Single(o => o.VersionBlockId == block.GetVersionBlockId()).DisplayModel }; mappedBlocks.Add(mappedBlock); } } return(mappedBlocks); }
private async Task <CustomEntityVersionPageBlockRenderDetails> MapAsync( CustomEntityVersionPageBlock versionBlock, string blockTypeFileName, string customEntityDefinitionCode, PublishStatusQuery publishStatus, IExecutionContext executionContext ) { _permissionValidationService.EnforceCustomEntityPermission <CustomEntityReadPermission>(customEntityDefinitionCode, executionContext.UserContext); var blockTypeQuery = new GetPageBlockTypeSummaryByIdQuery(versionBlock.PageBlockTypeId); var blockType = await _queryExecutor.ExecuteAsync(blockTypeQuery, executionContext); EntityNotFoundException.ThrowIfNull(blockType, versionBlock.PageBlockTypeId); var result = new CustomEntityVersionPageBlockRenderDetails(); result.CustomEntityVersionPageBlockId = versionBlock.CustomEntityVersionPageBlockId; result.BlockType = blockType; result.DisplayModel = await _pageVersionBlockModelMapper.MapDisplayModelAsync( blockTypeFileName, versionBlock, publishStatus, executionContext ); return(result); }
private async Task <PageVersionBlockRenderDetails> MapAsync( PageVersionBlock pageVersionBlock, string blockTypeFileName, PublishStatusQuery publishStatus, IExecutionContext executionContext ) { var blockTypeQuery = new GetPageBlockTypeSummaryByIdQuery(pageVersionBlock.PageBlockTypeId); var blockType = await _queryExecutor.ExecuteAsync(blockTypeQuery, executionContext); EntityNotFoundException.ThrowIfNull(blockType, pageVersionBlock.PageBlockTypeId); var result = new PageVersionBlockRenderDetails(); result.PageVersionBlockId = pageVersionBlock.PageVersionBlockId; result.BlockType = blockType; result.DisplayModel = await _pageVersionBlockModelMapper.MapDisplayModelAsync( blockTypeFileName, pageVersionBlock, publishStatus, executionContext ); return(result); }
private async Task <ICollection <MappedPageBlock> > ToBlockMappingDataAsync( IEnumerable <IEntityVersionPageBlock> entityBlocks, IEnumerable <PageBlockTypeSummary> blockTypes, PublishStatusQuery publishStatus, IExecutionContext executionContext ) { var mappedBlocks = new List <MappedPageBlock>(); foreach (var group in entityBlocks.GroupBy(m => m.PageBlockTypeId)) { var blockType = blockTypes.SingleOrDefault(t => t.PageBlockTypeId == group.Key); // If missing e.g. archived, skip if (blockType == null) { continue; } var mapperOutput = await _pageVersionBlockModelMapper.MapDisplayModelAsync( blockType.FileName, group, publishStatus, executionContext ); foreach (var block in group) { var versionBlockId = block.GetVersionBlockId(); if (mapperOutput.ContainsKey(versionBlockId) && mapperOutput[versionBlockId] != null) { var mappedBlock = new MappedPageBlock() { PageBlock = block, BlockType = blockType, DisplayModel = mapperOutput[versionBlockId] }; mappedBlocks.Add(mappedBlock); } } } return(mappedBlocks); }
/// <remarks> /// This has just been copied with slight modification from PagesController and /// needs to be refactored. /// </remarks> public async Task <ICollection <PageSearchResult> > ExecuteAsync(SearchPagesQuery query, IExecutionContext executionContext) { if (string.IsNullOrWhiteSpace(query.Text)) { return(Array.Empty <PageSearchResult>()); } var isAuthenticated = executionContext.UserContext.UserId.HasValue; // TODO: Search results should look at page titles as well as content blocks // Find any page versions that match by title // TODO: Ignore small words like 'of' and 'the' var titleMatchesPageVersions = (await _dbContext .Pages .Where(p => !p.IsDeleted && p.PageVersions.Any(pv => !pv.IsDeleted && isAuthenticated ? true : pv.WorkFlowStatusId == (int)WorkFlowStatus.Published) && !query.LocaleId.HasValue || p.LocaleId == query.LocaleId && p.PageTypeId == (int)PageType.Generic ) .Select(p => p.PageVersions .OrderByDescending(v => v.CreateDate) .First(pv => !pv.IsDeleted && isAuthenticated ? true : pv.WorkFlowStatusId == (int)WorkFlowStatus.Published) ) .ToListAsync()) .Where(v => v.Title.Contains(query.Text) || v.Title.ToLower().Split(new char[] { ' ' }).Intersect(query.Text.ToLower().Split(new char[] { ' ' })).Any() ) ; // TODO: Search should split the search term and lookup individual words as well (and rank them less strongly) // Get a list of ALL the page blocks for live pages - we'll search through these for any matches var pageBlocks = await _dbContext .PageVersionBlocks .Include(m => m.PageBlockType) .FilterActive() .Where(m => !m.PageVersion.IsDeleted) .Where(m => !m.PageVersion.Page.IsDeleted) .Where(m => isAuthenticated ? true : m.PageVersion.WorkFlowStatusId == (int)WorkFlowStatus.Published) .Where(m => !query.LocaleId.HasValue || m.PageVersion.Page.LocaleId == query.LocaleId) .Where(m => m.PageVersion.Page.PageTypeId == (int)PageType.Generic) .ToListAsync(); // This will store a list of matches for each block var matches = new Dictionary <PageVersionBlock, List <string> >(); foreach (var pageBlock in pageBlocks.Where(p => !string.IsNullOrEmpty(query.Text))) { var dataProvider = await _blockDisplayDataFactory.MapDisplayModelAsync(pageBlock.PageBlockType.FileName, pageBlock, PublishStatusQuery.Published); var dataProviderType = dataProvider.GetType().GetTypeInfo(); // If this block is searchable - ie there is content to search // TODO: Block Searching //if (dataProvider is ISearchable) //{ var props = dataProviderType .GetProperties() .Where(prop => prop.IsDefined(typeof(SearchableAttribute), true)); foreach (var prop in props) { string str = _htmlSanitizer.StripHtml(((string)prop.GetValue(dataProvider, null))); if (str.IndexOf(query.Text ?? "", StringComparison.OrdinalIgnoreCase) > -1) { if (!matches.ContainsKey(pageBlock)) { matches[pageBlock] = new List <string>(); } int index = str.ToLower().IndexOf(query.Text.ToLower()); int startIndex = index - 100; while (startIndex < 0) { startIndex++; } int length = (index - startIndex) + query.Text.Length + 100; while ((startIndex + length) > str.Length) { length--; } var matchStr = str.Substring(startIndex, length); // Stop the string at the last space if ((startIndex + length) < str.Length - 1 && matchStr.LastIndexOf(" ") > -1) { matchStr = matchStr.Substring(0, matchStr.LastIndexOf(" ")) + " …"; } // Stop the string at the first space if (startIndex > 0 && matchStr.IndexOf(" ") > -1) { matchStr = "… " + matchStr.Substring(matchStr.IndexOf(" ") + 1); } // Highlight the search term matchStr = Regex.Replace(matchStr, query.Text, @"<b>$0</b>", RegexOptions.IgnoreCase); matches[pageBlock].Add(matchStr); } } //} } // This is a list of pageversions matches to the number of matches var pageVersionMatches = matches .OrderByDescending(m => m.Value.Count) .GroupBy(m => m.Key.PageVersion.PageVersionId) .ToDictionary( g => g.First().Key.PageVersion, g => g.First().Value.Select(m => new HtmlString(m)) ); // Add any pages matched by title to the list of matches foreach (var pageVersion in titleMatchesPageVersions) { if (!pageVersionMatches.ContainsKey(pageVersion)) { pageVersionMatches.Add(pageVersion, null); } } var searchResults = new List <PageSearchResult>(); var pageroutes = await _queryExecutor.ExecuteAsync(new GetAllPageRoutesQuery(), executionContext); var results = new List <PageSearchResult>(pageVersionMatches.Count); foreach (var pageVersionMatch in pageVersionMatches .OrderByDescending(m => titleMatchesPageVersions.Contains(m.Key)) .ThenByDescending(m => m.Value == null ? 0 : m.Value.Count())) { var version = pageVersionMatch.Key; var route = pageroutes.SingleOrDefault(r => r.PageId == version.PageId); if (route != null) { var result = new PageSearchResult(); result.FoundText = pageVersionMatch.Value == null ? new HtmlString(version.MetaDescription) : pageVersionMatch.Value.First(); result.Title = version.Title; result.Url = route.FullPath; results.Add(result); } } return(results); }