public async Task <IEnumerable <PageBlockTypeDisplayModelMapperOutput> > MapAsync(
            IReadOnlyCollection <PageBlockTypeDisplayModelMapperInput <ContentSplitSectionDataModel> > inputCollection,
            PublishStatusQuery publishStatus
            )
        {
            // Because mapping is done in batch, we have to map multiple images here
            // Fortunately Cofoundry gives us access to repositories that can fetch this data
            // for us

            var imageAssetIds = inputCollection.SelectDistinctModelValuesWithoutEmpty(i => i.ImageAssetId);
            var imageAssets   = await _imageAssetRepository.GetImageAssetRenderDetailsByIdRangeAsync(imageAssetIds);

            var results = new List <PageBlockTypeDisplayModelMapperOutput>();

            foreach (var input in inputCollection)
            {
                var output = new ContentSplitSectionDisplayModel();
                output.HtmlText = new HtmlString(input.DataModel.HtmlText);
                output.Title    = input.DataModel.Title;
                output.Image    = imageAssets.GetOrDefault(input.DataModel.ImageAssetId);

                results.Add(input.CreateOutput(output));
            }

            return(results);
        }
Example #2
0
        public async Task <IEnumerable <PageBlockTypeDisplayModelMapperOutput> > MapAsync(
            IReadOnlyCollection <PageBlockTypeDisplayModelMapperInput <PageListDataModel> > inputCollection,
            PublishStatusQuery publishStatus
            )
        {
            var allPageIds = inputCollection.SelectManyDistinctModelValues(d => d.PageIds);

            // Page routes are cached and so are the quickest way to get simple page information.
            // If we needed more data we could use a different but slower query to get it.
            var query         = new GetPageRenderDetailsByIdRangeQuery(allPageIds);
            var allPageRoutes = await _pageRepository.GetPageRenderDetailsByIdRangeAsync(query);

            var results = new List <PageBlockTypeDisplayModelMapperOutput>(inputCollection.Count);

            foreach (var input in inputCollection)
            {
                var output = new PageListDisplayModel();

                // Here will get the relevant pages and order them correctly.
                // Additionally if we are viewing the published version of the page
                // then we make sure we only show published pages in the list.

                output.Pages = allPageRoutes
                               .FilterAndOrderByKeys(input.DataModel.PageIds)
                               .ToList();

                // The CreateOutput() method wraps the mapped display
                // model with it's identifier so we can identify later on
                results.Add(input.CreateOutput(output));
            }

            return(results);
        }
        private async Task <AuthorDetails> MapAuthor(
            BlogPostDataModel dataModel,
            PublishStatusQuery publishStatusQuery
            )
        {
            if (dataModel.AuthorId < 1)
            {
                return(null);
            }

            var authorQuery = new GetCustomEntityRenderSummaryByIdQuery(dataModel.AuthorId, publishStatusQuery.ToRelatedEntityQueryStatus());
            var dbAuthor    = await _customEntityRepository.GetCustomEntityRenderSummaryByIdAsync(authorQuery);

            var model = dbAuthor?.Model as AuthorDataModel;

            if (model == null)
            {
                return(null);
            }

            var author = new AuthorDetails()
            {
                Name      = dbAuthor.Title,
                Biography = HtmlFormatter.ConvertToBasicHtml(model.Biography)
            };

            if (model.ProfileImageAssetId < 1)
            {
                return(author);
            }

            author.ProfileImage = await _imageAssetRepository.GetImageAssetRenderDetailsByIdAsync(model.ProfileImageAssetId.Value);

            return(author);
        }
Example #4
0
        private async Task <List <PageBlockTypeDisplayModelMapperOutput> > MapGeneric <T>(
            IEnumerable <IEntityVersionPageBlock> pageBlocks,
            PublishStatusQuery publishStatusQuery
            ) where T : IPageBlockTypeDataModel
        {
            var mapperType = typeof(IPageBlockTypeDisplayModelMapper <T>);
            var mapper     = (IPageBlockTypeDisplayModelMapper <T>)_serviceProvider.GetService(mapperType);

            if (mapper == null)
            {
                string msg = @"{0} does not implement IPageBlockDisplayModel and no custom mapper could be found. You must create 
                               a class that implements IPageBlockDisplayModelMapper<{0}> if you are using a custom display model. Full type name: {1}";
                throw new Exception(string.Format(msg, typeof(T).Name, typeof(T).FullName));
            }

            var dataModels = new List <PageBlockTypeDisplayModelMapperInput <T> >();

            foreach (var pageBlock in pageBlocks)
            {
                var mapperModel = new PageBlockTypeDisplayModelMapperInput <T>();
                mapperModel.DataModel      = (T)_dbUnstructuredDataSerializer.Deserialize(pageBlock.SerializedData, typeof(T));
                mapperModel.VersionBlockId = pageBlock.GetVersionBlockId();
                dataModels.Add(mapperModel);
            }

            var results = await mapper.MapAsync(dataModels, publishStatusQuery);

            return(results.ToList());
        }
Example #5
0
        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);
        }
        public async Task <IEnumerable <PageBlockTypeDisplayModelMapperOutput> > MapAsync(
            IReadOnlyCollection <PageBlockTypeDisplayModelMapperInput <DocumentDataModel> > inputCollection,
            PublishStatusQuery publishStatusQuery
            )
        {
            var documentIds    = inputCollection.SelectDistinctModelValuesWithoutEmpty(i => i.DocumentAssetId);
            var documentsQuery = new GetDocumentAssetRenderDetailsByIdRangeQuery(documentIds);
            var documents      = await _queryExecutor.ExecuteAsync(documentsQuery);

            var results = new List <PageBlockTypeDisplayModelMapperOutput>(inputCollection.Count);

            foreach (var input in inputCollection)
            {
                var document = documents.GetOrDefault(input.DataModel.DocumentAssetId);

                var output = new DocumentDisplayModel();
                if (document != null)
                {
                    output.Description = document.Description;
                    output.Title       = document.Title;
                    if (input.DataModel.DownloadMode == DocumentDownloadMode.ForceDownload)
                    {
                        output.Url = _documentAssetRouteLibrary.DocumentAssetDownload(document);
                    }
                    else
                    {
                        output.Url = _documentAssetRouteLibrary.DocumentAsset(document);
                    }
                }

                results.Add(input.CreateOutput(output));
            }

            return(results);
        }
Example #7
0
        /// <summary>
        /// Maps a batch of the same type of page block data to a collection
        /// of display models ready for rendering.
        /// </summary>
        /// <param name="typeName">The block type name e.g. 'PlainText', 'RawHtml'.</param>
        /// <param name="pageBlocks">The version data to get the serialized model from.</param>
        /// <param name="publishStatus">
        /// The publish status of the parent page or custom entity
        /// being mapped. This is provided so dependent entities can use
        /// the same publish status.
        /// </param>
        /// <returns>
        /// Collection of mapped display models, wrapped in an output class that
        /// can be used to identify them.
        /// </returns>
        public async Task <ICollection <PageBlockTypeDisplayModelMapperOutput> > MapDisplayModelAsync(
            string typeName,
            IEnumerable <IEntityVersionPageBlock> pageBlocks,
            PublishStatusQuery publishStatus
            )
        {
            // Find the data-provider class for this block type
            Type modelType = _pageBlockDataModelTypeFactory.CreateByPageBlockTypeFileName(typeName);

            if (typeof(IPageBlockTypeDisplayModel).IsAssignableFrom(modelType))
            {
                // We can serialize directly to the display model
                var displayModels = new List <PageBlockTypeDisplayModelMapperOutput>();
                foreach (var pageBlock in pageBlocks)
                {
                    var mapperModel = new PageBlockTypeDisplayModelMapperOutput();
                    mapperModel.DisplayModel   = (IPageBlockTypeDisplayModel)_dbUnstructuredDataSerializer.Deserialize(pageBlock.SerializedData, modelType);
                    mapperModel.VersionBlockId = pageBlock.GetVersionBlockId();
                    displayModels.Add(mapperModel);
                }

                return(displayModels);
            }
            else
            {
                var blockWorkflowStatus = publishStatus.ToRelatedEntityQueryStatus();

                // We have to use a mapping class to do some custom mapping
                var displayModels = (Task <List <PageBlockTypeDisplayModelMapperOutput> >)_mapGenericMethod
                                    .MakeGenericMethod(modelType)
                                    .Invoke(this, new object[] { pageBlocks, blockWorkflowStatus });

                return(await displayModels);
            }
        }
        public async Task <BlogPostDisplayModel> MapDisplayModelAsync(
            CustomEntityRenderDetails renderDetails,
            BlogPostDataModel dataModel,
            PublishStatusQuery publishStatusQuery
            )
        {
            var vm = new BlogPostDisplayModel();

            vm.MetaDescription = dataModel.ShortDescription;
            vm.PageTitle       = renderDetails.Title;
            vm.Title           = renderDetails.Title;
            vm.Date            = renderDetails.CreateDate;
            vm.FullPath        = renderDetails.PageUrls.FirstOrDefault();

            if (!EnumerableHelper.IsNullOrEmpty(dataModel.CategoryIds))
            {
                // We manually query and map relations which gives us maximum flexibility when mapping models
                // Fortunately the framework provides tools to make this fairly simple
                vm.Categories = await _contentRepository
                                .CustomEntities()
                                .GetByIdRange(dataModel.CategoryIds)
                                .AsRenderSummaries(publishStatusQuery)
                                .MapItem(MapCategory)
                                .FilterAndOrderByKeys(dataModel.CategoryIds)
                                .ExecuteAsync();
            }

            return(vm);
        }
Example #9
0
    private async Task<PagedQueryResult<BlogPostSummary>> MapBlogPostsAsync(
        PagedQueryResult<CustomEntityRenderSummary> customEntityResult,
        PublishStatusQuery ambientEntityPublishStatusQuery)
    {
      var blogPosts = new List<BlogPostSummary>();

      var imageAssetIds = customEntityResult
          .Items
          .Select(i => (BlogPostDataModel)i.Model)
          .Where(m => m.ThumbnailImageAssetId != null)
          .Select(m => m.ThumbnailImageAssetId.Value)
          .Distinct();

      var imageLookup = await _contentRepository
          .ImageAssets()
          .GetByIdRange(imageAssetIds)
          .AsRenderDetails()
          .ExecuteAsync();

      foreach (var customEntity in customEntityResult.Items)
      {
        var model = (BlogPostDataModel)customEntity.Model;

        var blogPost = new BlogPostSummary();
        blogPost.Title = customEntity.Title;
        blogPost.ShortDescription = model.ShortDescription;
        blogPost.ThumbnailImageAsset = imageLookup.GetOrDefault(model.ThumbnailImageAssetId);
        blogPost.FullPath = customEntity.PageUrls.FirstOrDefault();
        blogPost.PostDate = customEntity.PublishDate;

        blogPosts.Add(blogPost);
      }

      return customEntityResult.ChangeType(blogPosts);
    }
Example #10
0
        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);
        }
Example #11
0
 public GetCustomEntitySummariesByIdRangeQuery(
     IEnumerable <int> customEntityIds,
     PublishStatusQuery publishStatusQuery = PublishStatusQuery.Published
     )
     : this(customEntityIds?.ToList())
 {
 }
Example #12
0
        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);
        }
Example #13
0
        public async Task <IEnumerable <PageBlockTypeDisplayModelMapperOutput> > MapAsync(
            IReadOnlyCollection <PageBlockTypeDisplayModelMapperInput <ImageDataModel> > inputCollection,
            PublishStatusQuery publishStatusQuery
            )
        {
            var imageAssetIds = inputCollection.SelectDistinctModelValuesWithoutEmpty(i => i.ImageId);
            var imagesQuery   = new GetImageAssetRenderDetailsByIdRangeQuery(imageAssetIds);
            var images        = await _queryExecutor.ExecuteAsync(imagesQuery);

            var results = new List <PageBlockTypeDisplayModelMapperOutput>(inputCollection.Count);

            foreach (var input in inputCollection)
            {
                var output = new ImageDisplayModel()
                {
                    AltText    = input.DataModel.AltText,
                    LinkPath   = input.DataModel.LinkPath,
                    LinkTarget = input.DataModel.LinkTarget
                };

                var image = images.GetOrDefault(input.DataModel.ImageId);
                output.Source = _imageAssetRouteLibrary.ImageAsset(image);

                results.Add(input.CreateOutput(output));
            }

            return(results);
        }
Example #14
0
 public Task <IEnumerable <PageBlockTypeDisplayModelMapperOutput> > MapAsync(
     IReadOnlyCollection <PageBlockTypeDisplayModelMapperInput <SingleLineTextDataModel> > inputCollection,
     PublishStatusQuery publishStatusQuery
     )
 {
     return(Task.FromResult(Map(inputCollection)));
 }
        public async Task WhenQueriedWithPublishStatus_ReturnsCorrectWorkflowStatus(
            PublishStatusQuery publishStatus,
            WorkFlowStatus?draftOnlyWorkFlowStatus,
            WorkFlowStatus?publishOnlyWorkFlowStatus,
            WorkFlowStatus?publishAndDraftWorkFlowStatus
            )
        {
            var uniqueData = UNIQUE_PREFIX + "QPubStatus_" + publishStatus;

            using var app = _appFactory.Create();
            var directoryId = await app.TestData.PageDirectories().AddAsync(uniqueData);

            var pageWithDraftOnlyId = await app.TestData.Pages().AddAsync(uniqueData + "_D", directoryId);

            var pageWithPublishedOnlyId = await app.TestData.Pages().AddAsync(uniqueData + "_P", directoryId, c => c.Publish = true);

            var pageWithPublishedandDraftId = await app.TestData.Pages().AddAsync(uniqueData + "_DP", directoryId, c => c.Publish = true);

            await app.TestData.Pages().AddDraftAsync(pageWithPublishedandDraftId);

            var contentRepository = app.Services.GetContentRepositoryWithElevatedPermissions();
            var pages             = await contentRepository
                                    .Pages()
                                    .GetByIdRange(new int[] { pageWithDraftOnlyId, pageWithPublishedOnlyId, pageWithPublishedandDraftId })
                                    .AsRenderSummaries(publishStatus)
                                    .ExecuteAsync();

            AssertStatus(pages, pageWithDraftOnlyId, draftOnlyWorkFlowStatus);
            AssertStatus(pages, pageWithPublishedOnlyId, publishOnlyWorkFlowStatus);
            AssertStatus(pages, pageWithPublishedandDraftId, publishAndDraftWorkFlowStatus);
Example #16
0
        protected async Task <IReadOnlyDictionary <int, IPageBlockTypeDisplayModel> > MapGeneric <TDataModel>(
            IEnumerable <IEntityVersionPageBlock> pageBlocks,
            PublishStatusQuery publishStatusQuery,
            IExecutionContext executionContext
            ) where TDataModel : IPageBlockTypeDataModel
        {
            var mapperType = typeof(IPageBlockTypeDisplayModelMapper <TDataModel>);
            var mapper     = (IPageBlockTypeDisplayModelMapper <TDataModel>)_serviceProvider.GetService(mapperType);

            if (mapper == null)
            {
                string msg = @"{0} does not implement IPageBlockDisplayModel and no custom mapper could be found. You must create 
                               a class that implements IPageBlockDisplayModelMapper<{0}> if you are using a custom display model. Full type name: {1}";
                throw new Exception(string.Format(msg, typeof(TDataModel).Name, typeof(TDataModel).FullName));
            }

            var dataModels = new List <PageBlockTypeDisplayModelMapperInput <TDataModel> >();

            foreach (var pageBlock in pageBlocks)
            {
                var mapperModel = new PageBlockTypeDisplayModelMapperInput <TDataModel>();
                mapperModel.DataModel      = (TDataModel)_dbUnstructuredDataSerializer.Deserialize(pageBlock.SerializedData, typeof(TDataModel));
                mapperModel.VersionBlockId = pageBlock.GetVersionBlockId();
                dataModels.Add(mapperModel);
            }

            var context = new PageBlockTypeDisplayModelMapperContext <TDataModel>(dataModels, publishStatusQuery, executionContext);
            var result  = new PageBlockTypeDisplayModelMapperResult <TDataModel>(dataModels.Count);
            await mapper.MapAsync(context, result);

            return(result.Items);
        }
        public async Task <BlogPostDisplayModel> MapDisplayModelAsync(
            CustomEntityRenderDetails renderDetails,
            BlogPostDataModel dataModel,
            PublishStatusQuery publishStatusQuery
            )
        {
            var vm = new BlogPostDisplayModel();

            vm.MetaDescription = dataModel.ShortDescription;
            vm.PageTitle       = renderDetails.Title;
            vm.Title           = renderDetails.Title;
            vm.Date            = renderDetails.CreateDate;
            vm.FullPath        = renderDetails.PageUrls.FirstOrDefault();

            if (!EnumerableHelper.IsNullOrEmpty(dataModel.CategoryIds))
            {
                // We manually query and map relations which gives us maximum flexibility when mapping models
                // Fortunately the framework provides tools to make this fairly simple
                var relatedEntityPublishStatusQuery = publishStatusQuery.ToRelatedEntityQueryStatus();
                var categoriesQuery = new GetCustomEntityRenderSummariesByIdRangeQuery(dataModel.CategoryIds, relatedEntityPublishStatusQuery);
                var customEntities  = await _customEntityRepository.GetCustomEntityRenderSummariesByIdRangeAsync(categoriesQuery);

                vm.Categories = customEntities
                                .FilterAndOrderByKeys(dataModel.CategoryIds)
                                .Select(c => MapCategory(c))
                                .ToList();
            }

            return(vm);
        }
 public GetCustomEntityRenderSummariesByDefinitionCodeQuery(
     string customEntityDefinitionCode,
     PublishStatusQuery workflowStatus = PublishStatusQuery.Published
     )
 {
     CustomEntityDefinitionCode = customEntityDefinitionCode;
     PublishStatus = workflowStatus;
 }
Example #19
0
 /// <summary>
 /// Query to retreive all custom entites of a specific type, projected as a
 /// CustomEntityRenderSummary, which is a general-purpose projection with version
 /// specific data, including a deserialized data model. The results are
 /// version-sensitive and defaults to returning published versions only, but
 /// this behavior can be controlled by the publishStatus query property.
 /// </summary>
 /// <param name="customEntityDefinitionCode">The definition code of the custom entity to filter on.</param>
 /// <param name="publicStatusQuery">
 /// Used to determine which version of the custom entities to include data for. This
 /// defaults to Published, meaning that only published custom entities will be returned.
 /// </param>
 public GetCustomEntityRenderSummariesByDefinitionCodeQuery(
     string customEntityDefinitionCode,
     PublishStatusQuery publicStatusQuery = PublishStatusQuery.Published
     )
 {
     CustomEntityDefinitionCode = customEntityDefinitionCode;
     PublishStatus = publicStatusQuery;
 }
Example #20
0
        /// <summary>
        /// Turns the PublishStatusQuery used to query an entity into a PublishStatusQuery
        /// that can be used to query dependent entities. E.g. PublishStatusQuery.SpecificVersion
        /// cannot be used to query a dependent entity and so PublishStatusQuery.Latest is
        /// used instead.
        /// </summary>
        /// <remarks>
        /// When working with child entities, the PublishStatusQuery we apply to
        /// them is not neccessarily the status used to query the parent. If we are
        /// loading a page using the Draft status, then we cannot expect that all
        /// dependencies should have a draft version, so we re-write it to Latest.
        /// The same applies if we're loading a specific version.
        /// </remarks>
        public static PublishStatusQuery ToRelatedEntityQueryStatus(this PublishStatusQuery publishStatusQuery)
        {
            if (publishStatusQuery == PublishStatusQuery.Draft || publishStatusQuery == PublishStatusQuery.SpecificVersion)
            {
                publishStatusQuery = PublishStatusQuery.Latest;
            }

            return(publishStatusQuery);
        }
Example #21
0
 /// <summary>
 /// Returns custom entities filtered on the url slug value. This query
 /// can return multiple custom entities because unique UrlSlugs is an
 /// optional setting on the custom entity definition.
 /// </summary>
 /// <param name="customEntityDefinitionCode">Required. The definition code of the custom entity to filter on.</param>
 /// <param name="urlSlug">Required. The url slug to find matching custom entities for.</param>
 /// <param name="publishStatusQuery">
 /// Used to determine which version of the custom entities to include data for. This
 /// defaults to Published, meaning that only published custom entities will be returned.
 /// Note that PublishStatusQuery.SpecificVersion is not available
 /// because the query can potentially return multiple results.
 /// </param>
 public GetCustomEntityRenderSummariesByUrlSlugQuery(
     string customEntityDefinitionCode,
     string urlSlug,
     PublishStatusQuery publishStatusQuery = PublishStatusQuery.Published
     )
 {
     CustomEntityDefinitionCode = customEntityDefinitionCode;
     UrlSlug       = urlSlug;
     PublishStatus = publishStatusQuery;
 }
Example #22
0
        /// <summary>
        /// Maps a single page block data model to a concrete
        /// display model.
        /// </summary>
        /// <param name="typeName">The block type name e.g. 'PlainText', 'RawHtml'.</param>
        /// <param name="pageBlock">The version data to get the serialized model from.</param>
        /// <param name="publishStatus">
        /// The publish status of the parent page or custom entity
        /// being mapped. This is provided so dependent entities can use
        /// the same publish status.
        /// </param>
        /// <returns>Mapped display model.</returns>
        public async Task <IPageBlockTypeDisplayModel> MapDisplayModelAsync(
            string typeName,
            IEntityVersionPageBlock pageBlock,
            PublishStatusQuery publishStatus
            )
        {
            var mapped = await MapDisplayModelAsync(typeName, new IEntityVersionPageBlock[] { pageBlock }, publishStatus);

            return(mapped
                   .Select(m => m.DisplayModel)
                   .SingleOrDefault());
        }
Example #23
0
        public GetCustomEntitySummariesByIdRangeQuery(
            IReadOnlyCollection <int> customEntityIds,
            PublishStatusQuery publishStatusQuery = PublishStatusQuery.Published
            )
        {
            if (customEntityIds == null)
            {
                throw new ArgumentNullException(nameof(customEntityIds));
            }

            CustomEntityIds = customEntityIds;
            PublishStatus   = publishStatusQuery;
        }
        /// <summary>
        /// Maps custom entity render data into a specific custom entity
        /// display model type, which can be used to render out view data.
        /// </summary>
        /// <typeparam name="TDisplayModel">Display model type to map to.</typeparam>
        /// <param name="renderDetails">The custom entity model to map, including the raw data model.</param>
        /// <param name="publishStatusQuery">
        /// The query type that should be used to query dependent entities. E.g. if the custom
        /// entity was queried with the Published status query, then any dependent entities should
        /// also be queried as Published.
        /// </param>
        /// <returns>Mapped display model instance.</returns>
        public Task <TDisplayModel> MapDisplayModelAsync <TDisplayModel>(
            CustomEntityRenderDetails renderDetails,
            PublishStatusQuery publishStatusQuery
            )
            where TDisplayModel : ICustomEntityDisplayModel
        {
            var mapperType = typeof(ICustomEntityDisplayModelMapper <,>).MakeGenericType(renderDetails.Model.GetType(), typeof(TDisplayModel));
            var mapper     = _serviceProvider.GetRequiredService(mapperType);

            var method = mapperType.GetMethod(mapDisplayModelMethodName);

            return((Task <TDisplayModel>)method.Invoke(mapper, new object[] { renderDetails, renderDetails.Model, publishStatusQuery }));
        }
        public Task <TestCustomEntityPageDisplayModel> MapDisplayModelAsync(
            CustomEntityRenderDetails renderDetails,
            TestCustomEntityDataModel dataModel,
            PublishStatusQuery publishStatusQuery
            )
        {
            var displayModel = new TestCustomEntityPageDisplayModel()
            {
                PageTitle       = renderDetails.Title,
                MetaDescription = "Test Meta Description"
            };

            return(Task.FromResult(displayModel));
        }
Example #26
0
 /// <summary>
 /// Validates that a query model has a valid version id property
 /// for the provided PublishStatusQuery value. E.g. the version id
 /// should only be specified if the publish status is set to
 /// PublishStatusQuery.SpecificVersion. Any errors are returned as
 /// validation results, intended to be used in an IValidatableObject
 /// implementation.
 /// </summary>
 /// <param name="publishStatusQuery">PublishStatusQuery value to check.</param>
 /// <param name="pageVersionId">Version id property to check.</param>
 /// <param name="versionIdPropertyName">The name of the version id property to return in any error messages.</param>
 public static IEnumerable <ValidationResult> ValidateVersionId(
     PublishStatusQuery publishStatusQuery,
     int?pageVersionId,
     string versionIdPropertyName
     )
 {
     if (publishStatusQuery == PublishStatusQuery.SpecificVersion && (!pageVersionId.HasValue || pageVersionId < 1))
     {
         yield return(new ValidationResult($"Value cannot be null if {nameof(PublishStatusQuery)}.{nameof(PublishStatusQuery.SpecificVersion)} is specified", new string[] { versionIdPropertyName }));
     }
     else if (publishStatusQuery != PublishStatusQuery.SpecificVersion && pageVersionId.HasValue)
     {
         yield return(new ValidationResult($"Value should be null if {nameof(PublishStatusQuery)}.{nameof(PublishStatusQuery.SpecificVersion)} is not specified", new string[] { versionIdPropertyName }));
     }
 }
Example #27
0
        /// <summary>
        /// Gets version routing info for the specified PublishStatus query
        /// </summary>
        public static T GetVersionRouting <T>(this IEnumerable <T> versions, PublishStatusQuery status, int?versionId = null)
            where T : IVersionRoute
        {
            T result;

            switch (status)
            {
            case PublishStatusQuery.Draft:
                result = versions
                         .SingleOrDefault(v => v.WorkFlowStatus == WorkFlowStatus.Draft);
                break;

            case PublishStatusQuery.Published:
                result = versions
                         .Where(v => v.WorkFlowStatus == WorkFlowStatus.Published)
                         .OrderByDescending(v => v.CreateDate)
                         .FirstOrDefault();
                break;

            case PublishStatusQuery.Latest:
                result = versions
                         .Where(v => v.WorkFlowStatus == WorkFlowStatus.Draft || v.WorkFlowStatus == WorkFlowStatus.Published)
                         .OrderByDescending(v => v.WorkFlowStatus == WorkFlowStatus.Draft)
                         .FirstOrDefault();
                break;

            case PublishStatusQuery.PreferPublished:
                result = versions
                         .Where(v => v.WorkFlowStatus == WorkFlowStatus.Draft || v.WorkFlowStatus == WorkFlowStatus.Published)
                         .OrderByDescending(v => v.WorkFlowStatus == WorkFlowStatus.Published)
                         .FirstOrDefault();
                break;

            case PublishStatusQuery.SpecificVersion:
                if (!versionId.HasValue)
                {
                    throw new InvalidOperationException("PublishStatusQuery.SpecificVersion requires a specific VersionId");
                }
                result = versions
                         .SingleOrDefault(v => v.VersionId == versionId);
                break;

            default:
                throw new InvalidOperationException("Unrecognised PublishStatusQuery: " + status);
            }

            return(result);
        }
        /// <summary>
        /// Here we map the raw custom entity data from Cofoundry into our
        /// own BlogPostSummary which will get sent to be rendered in the
        /// view.
        ///
        /// This code is repeated in HomepageBlogPostsViewComponent for
        /// simplicity, but typically you'd put the code into a shared
        /// mapper or break data access out into it's own shared layer.
        /// </summary>
        private async Task <PagedQueryResult <BlogPostSummary> > MapBlogPostsAsync(
            PagedQueryResult <CustomEntityRenderSummary> customEntityResult,
            PublishStatusQuery ambientEntityPublishStatusQuery
            )
        {
            var blogPosts = new List <BlogPostSummary>(customEntityResult.Items.Count());

            var imageAssetIds = customEntityResult
                                .Items
                                .Select(i => (BlogPostDataModel)i.Model)
                                .Select(m => m.ThumbnailImageAssetId)
                                .Distinct();

            var authorIds = customEntityResult
                            .Items
                            .Select(i => (BlogPostDataModel)i.Model)
                            .Select(m => m.AuthorId)
                            .Distinct();

            var imageLookup = await _imageAssetRepository.GetImageAssetRenderDetailsByIdRangeAsync(imageAssetIds);

            var authorQuery  = new GetCustomEntityRenderSummariesByIdRangeQuery(authorIds, ambientEntityPublishStatusQuery);
            var authorLookup = await _customEntityRepository.GetCustomEntityRenderSummariesByIdRangeAsync(authorQuery);

            foreach (var customEntity in customEntityResult.Items)
            {
                var model = (BlogPostDataModel)customEntity.Model;

                var blogPost = new BlogPostSummary();
                blogPost.Title               = customEntity.Title;
                blogPost.ShortDescription    = model.ShortDescription;
                blogPost.ThumbnailImageAsset = imageLookup.GetOrDefault(model.ThumbnailImageAssetId);
                blogPost.FullPath            = customEntity.PageUrls.FirstOrDefault();
                blogPost.PostDate            = customEntity.PublishDate;

                var author = authorLookup.GetOrDefault(model.AuthorId);
                if (author != null)
                {
                    blogPost.AuthorName = author.Title;
                }

                blogPosts.Add(blogPost);
            }

            return(customEntityResult.ChangeType(blogPosts));
        }
Example #29
0
        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);
        }
Example #30
0
        public Task <IEnumerable <PageBlockTypeDisplayModelMapperOutput> > MapAsync(
            IReadOnlyCollection <PageBlockTypeDisplayModelMapperInput <RichTextWithMediaDataModel> > inputCollection,
            PublishStatusQuery publishStatusQuery
            )
        {
            var results = new List <PageBlockTypeDisplayModelMapperOutput>(inputCollection.Count);

            foreach (var input in inputCollection)
            {
                var output = new RichTextWithMediaDisplayModel();
                output.RawHtml = new HtmlString(input.DataModel.RawHtml);

                results.Add(input.CreateOutput(output));
            }

            return(Task.FromResult(results.AsEnumerable()));
        }