/// <summary> /// Populates a Dynamic List by executing the query it specifies. /// </summary> /// <param name="dynamicList">The Dynamic List which specifies the query and is to be populated.</param> /// <param name="localization">The context Localization.</param> public void PopulateDynamicList(DynamicList dynamicList, Localization localization) { using (new Tracer(dynamicList, localization)) { SimpleBrokerQuery simpleBrokerQuery = dynamicList.GetQuery(localization) as SimpleBrokerQuery; if (simpleBrokerQuery == null) { throw new DxaException($"Unexpected result from {dynamicList.GetType().Name}.GetQuery: {dynamicList.GetQuery(localization)}"); } BrokerQuery brokerQuery = new BrokerQuery(simpleBrokerQuery); string[] componentUris = brokerQuery.ExecuteQuery().ToArray(); Log.Debug($"Broker Query returned {componentUris.Length} results. HasMore={brokerQuery.HasMore}"); if (componentUris.Length > 0) { Type resultType = dynamicList.ResultType; ComponentMetaFactory componentMetaFactory = new ComponentMetaFactory(localization.GetCmUri()); dynamicList.QueryResults = componentUris .Select(c => ModelBuilderPipeline.CreateEntityModel(CreateEntityModelData(componentMetaFactory.GetMeta(c)), resultType, localization)) .ToList(); } dynamicList.HasMore = brokerQuery.HasMore; } }
protected virtual object MapRichText(RichTextData richTextData, Type targetType, ILocalization localization) { IList <IRichTextFragment> fragments = new List <IRichTextFragment>(); foreach (object fragment in richTextData.Fragments) { string htmlFragment = fragment as string; if (htmlFragment == null) { // Embedded Entity Model (for Media Items) MediaItem mediaItem = (MediaItem)ModelBuilderPipeline.CreateEntityModel((EntityModelData)fragment, typeof(MediaItem), localization); mediaItem.IsEmbedded = true; if (mediaItem.MvcData == null) { mediaItem.MvcData = mediaItem.GetDefaultView(localization); } fragments.Add(mediaItem); } else { // HTML fragment. fragments.Add(new RichTextFragment(htmlFragment)); } } RichText richText = new RichText(fragments); if (targetType == typeof(RichText)) { return(richText); } return(richText.ToString()); }
/// <summary> /// Gets an Entity Model for a given Entity Identifier. /// </summary> /// <param name="id">The Entity Identifier in format ComponentID-TemplateID.</param> /// <param name="localization">The context Localization.</param> /// <returns>The Entity Model.</returns> /// <exception cref="DxaItemNotFoundException">If no Entity Model exists for the given URL.</exception> /// <remarks> /// Since we can't obtain CT metadata for DCPs, we obtain the View Name from the CT Title. /// </remarks> public virtual EntityModel GetEntityModel(string id, Localization localization) { using (new Tracer(id, localization)) { string[] idParts = id.Split('-'); if (idParts.Length != 2) { throw new DxaException(String.Format("Invalid Entity Identifier '{0}'. Must be in format ComponentID-TemplateID.", id)); } string componentUri = string.Format("tcm:{0}-{1}", localization.LocalizationId, idParts[0]); string templateUri = string.Format("tcm:{0}-{1}-32", localization.LocalizationId, idParts[1]); IComponentPresentationFactory componentPresentationFactory = DD4TFactoryCache.GetComponentPresentationFactory(localization); IComponentPresentation dcp; if (!componentPresentationFactory.TryGetComponentPresentation(out dcp, componentUri, templateUri)) { throw new DxaItemNotFoundException(id, localization.LocalizationId); } EntityModel result = ModelBuilderPipeline.CreateEntityModel(dcp, localization); if (result.XpmMetadata != null) { // Entity Models requested through this method are per definition "query based" in XPM terminology. result.XpmMetadata["IsQueryBased"] = true; } return(result); } }
protected virtual object MapRichText(RichTextData richTextData, Type targetType, Localization localization) { IList <IRichTextFragment> fragments = new List <IRichTextFragment>(); foreach (object fragment in richTextData.Fragments) { string htmlFragment = fragment as string; if (htmlFragment == null) { var entityModelData = (EntityModelData)fragment; EntityModel embeddedItem = ModelBuilderPipeline.CreateEntityModel(entityModelData, entityModelData.BinaryContent != null ? typeof(MediaItem) : typeof(EntityModel), localization); if (embeddedItem.MvcData == null) { embeddedItem.MvcData = embeddedItem.GetDefaultView(localization); } embeddedItem.IsEmbedded = true; fragments.Add(embeddedItem); } else { // HTML fragment. fragments.Add(new RichTextFragment(htmlFragment)); } } RichText richText = new RichText(fragments); if (targetType == typeof(RichText)) { return(richText); } return(richText.ToString()); }
protected virtual object MapComponentLink(EntityModelData entityModelData, Type targetType, Localization localization) { if (targetType == typeof(Link)) { return(new Link { Id = entityModelData.Id, Url = GetLinkUrl(entityModelData, localization) }); } if (targetType == typeof(string)) { return(GetLinkUrl(entityModelData, localization)); } if (!typeof(EntityModel).IsAssignableFrom(targetType)) { throw new DxaException($"Cannot map Component Link to property of type '{targetType.Name}'."); } if (string.IsNullOrWhiteSpace(entityModelData.SchemaId)) { return(null); } return(ModelBuilderPipeline.CreateEntityModel(entityModelData, targetType, localization)); }
/// <summary> /// Populates a Dynamic List by executing the query it specifies. /// </summary> /// <param name="dynamicList">The Dynamic List which specifies the query and is to be populated.</param> /// <param name="localization">The context Localization.</param> public override void PopulateDynamicList(DynamicList dynamicList, Localization localization) { using (new Tracer(dynamicList, localization)) { SimpleBrokerQuery simpleBrokerQuery = dynamicList.GetQuery(localization) as SimpleBrokerQuery; if (simpleBrokerQuery == null) { throw new DxaException($"Unexpected result from {dynamicList.GetType().Name}.GetQuery: {dynamicList.GetQuery(localization)}"); } // get our cursor indexer for this list var cursors = CursorIndexer.GetCursorIndexer(dynamicList.Id); // given our start index into the paged list we need to translate that to a cursor int start = simpleBrokerQuery.Start; simpleBrokerQuery.Cursor = cursors[start]; // the cursor retrieved may of came from a different start index so we update start int startIndex = cursors.StartIndex; simpleBrokerQuery.Start = startIndex; dynamicList.Start = startIndex; var cachedDynamicList = SiteConfiguration.CacheProvider.GetOrAdd( $"PopulateDynamicList-{dynamicList.Id}-{simpleBrokerQuery.GetHashCode()}", // key CacheRegions.BrokerQuery, () => { var brokerQuery = new GraphQLQueryProvider(); var components = brokerQuery.ExecuteQueryItems(simpleBrokerQuery).ToList(); Log.Debug($"Broker Query returned {components.Count} results. HasMore={brokerQuery.HasMore}"); if (components.Count > 0) { Type resultType = dynamicList.ResultType; dynamicList.QueryResults = components .Select( c => ModelBuilderPipeline.CreateEntityModel( CreateEntityModelData((Component)c), resultType, localization)) .ToList(); } dynamicList.HasMore = brokerQuery.HasMore; if (brokerQuery.HasMore) { // update cursor cursors[simpleBrokerQuery.Start + simpleBrokerQuery.PageSize] = brokerQuery.Cursor; } return(dynamicList); }); dynamicList.QueryResults = cachedDynamicList.QueryResults; dynamicList.HasMore = cachedDynamicList.HasMore; } }
/// <summary> /// Gets an Entity Model for a given Entity Identifier. /// </summary> /// <param name="id">The Entity Identifier in format ComponentID-TemplateID.</param> /// <param name="localization">The context Localization.</param> /// <returns>The Entity Model.</returns> /// <exception cref="DxaItemNotFoundException">If no Entity Model exists for the given URL.</exception> /// <remarks> /// Since we can't obtain CT metadata for DCPs, we obtain the View Name from the CT Title. /// </remarks> public virtual EntityModel GetEntityModel(string id, Localization localization) { using (new Tracer(id, localization)) { string[] idParts = id.Split('-'); if (idParts.Length != 2) { throw new DxaException(String.Format("Invalid Entity Identifier '{0}'. Must be in format ComponentID-TemplateID.", id)); } string componentUri = localization.GetCmUri(idParts[0]); string templateUri = localization.GetCmUri(idParts[1], (int)ItemType.ComponentTemplate); IComponentPresentationFactory componentPresentationFactory = DD4TFactoryCache.GetComponentPresentationFactory(localization); IComponentPresentation dcp; if (!componentPresentationFactory.TryGetComponentPresentation(out dcp, componentUri, templateUri)) { throw new DxaItemNotFoundException(id, localization.Id); } EntityModel result; if (CacheRegions.IsViewModelCachingEnabled) { EntityModel cachedEntityModel = SiteConfiguration.CacheProvider.GetOrAdd( string.Format("{0}-{1}", id, localization.Id), // key CacheRegions.EntityModel, () => ModelBuilderPipeline.CreateEntityModel(dcp, localization), dependencies: new[] { componentUri } ); // Don't return the cached Entity Model itself, because we don't want dynamic logic to modify the cached state. result = (EntityModel)cachedEntityModel.DeepCopy(); } else { result = ModelBuilderPipeline.CreateEntityModel(dcp, localization); } if (result.XpmMetadata != null) { // Entity Models requested through this method are per definition "query based" in XPM terminology. result.XpmMetadata["IsQueryBased"] = true; } return(result); } }
protected virtual PageModel LoadPageModel(int pageId, bool addIncludes, Localization localization) { using (new Tracer(pageId, addIncludes, localization)) { PageModelData pageModelData = SiteConfiguration.ModelServiceProvider.GetPageModelData(pageId, localization, addIncludes); if (pageModelData == null) { throw new DxaItemNotFoundException($"Page not found for publication id {localization.Id} and page id {pageId}"); } if (pageModelData.MvcData == null) { throw new DxaException($"Data Model for Page '{pageModelData.Title}' ({pageModelData.Id}) contains no MVC data. Ensure that the Page is published using the DXA R2 TBBs."); } return(ModelBuilderPipeline.CreatePageModel(pageModelData, addIncludes, localization)); } }
private PageModel LoadPageModel(ref string urlPath, bool addIncludes, Localization localization) { using (new Tracer(urlPath, addIncludes, localization)) { PageModelData pageModelData = SiteConfiguration.ModelServiceProvider.GetPageModelData(urlPath, localization, addIncludes); if (pageModelData == null) { throw new DxaItemNotFoundException(urlPath); } if (pageModelData.MvcData == null) { throw new DxaException($"Data Model for Page '{pageModelData.Title}' ({pageModelData.Id}) contains no MVC data. Ensure that the Page is published using the DXA R2 TBBs."); } return(ModelBuilderPipeline.CreatePageModel(pageModelData, addIncludes, localization)); } }
protected virtual RegionModel CreateRegionModel(RegionModelData regionModelData, ILocalization localization) { MvcData mvcData = CreateMvcData(regionModelData.MvcData, "Region"); Type regionModelType = ModelTypeRegistry.GetViewModelType(mvcData); RegionModel result = (RegionModel)regionModelType.CreateInstance(regionModelData.Name); result.ExtensionData = regionModelData.ExtensionData; result.HtmlClasses = regionModelData.HtmlClasses; result.MvcData = mvcData; result.XpmMetadata = localization.IsXpmEnabled ? regionModelData.XpmMetadata : null; if (regionModelData.Regions != null) { IEnumerable <RegionModel> nestedRegionModels = regionModelData.Regions.Select(data => CreateRegionModel(data, localization)); result.Regions.UnionWith(nestedRegionModels); result.IsVolatile |= result.Regions.Any(region => region.IsVolatile); } if (regionModelData.Entities != null) { foreach (EntityModelData entityModelData in regionModelData.Entities) { EntityModel entityModel; try { entityModel = ModelBuilderPipeline.CreateEntityModel(entityModelData, null, localization); // indicate to region model that this region is potentially volatile if it contains a volatile entity result.IsVolatile |= entityModel.IsVolatile; entityModel.MvcData.RegionName = regionModelData.Name; } catch (Exception ex) { // If there is a problem mapping an Entity, we replace it with an ExceptionEntity which holds the error details and carry on. Log.Error(ex); entityModel = new ExceptionEntity(ex); } result.Entities.Add(entityModel); } } return(result); }
private EntityModel LoadEntityModel(string id, Localization localization) { using (new Tracer(id, localization)) { EntityModelData entityModelData = SiteConfiguration.ModelServiceProvider.GetEntityModelData(id, localization); if (entityModelData == null) { throw new DxaItemNotFoundException(id); } EntityModel result = ModelBuilderPipeline.CreateEntityModel(entityModelData, null, localization); if (result.XpmMetadata != null) { // Entity Models requested through this method are per definition "query based" in XPM terminology. result.XpmMetadata["IsQueryBased"] = true; // TODO TSI-24: Do this in Model Service (or CM-side?) } return(result); } }
#pragma warning restore 618 /// <summary> /// Gets a Page Model for a given URL. /// </summary> /// <param name="url">The URL.</param> /// <param name="localization">The context Localization.</param> /// <param name="addIncludes">Indicates whether include Pages should be expanded.</param> /// <returns>The Page Model.</returns> /// <exception cref="DxaItemNotFoundException">If no Page Model exists for the given URL.</exception> public virtual PageModel GetPageModel(string url, Localization localization, bool addIncludes) { using (new Tracer(url, localization, addIncludes)) { //We can have a couple of tries to get the page model if there is no file extension on the url request, but it does not end in a slash: //1. Try adding the default extension, so /news becomes /news.html IPage page = GetPage(url, localization); if (page == null && (url == null || (!url.EndsWith("/") && url.LastIndexOf(".", StringComparison.Ordinal) <= url.LastIndexOf("/", StringComparison.Ordinal)))) { //2. Try adding the default page, so /news becomes /news/index.html page = GetPage(url + "/", localization); } if (page == null) { throw new DxaItemNotFoundException(url); } FullyLoadDynamicComponentPresentations(page, localization); IPage[] includes = addIncludes ? GetIncludesFromModel(page, localization).ToArray() : new IPage[0]; return(ModelBuilderPipeline.CreatePageModel(page, includes, localization)); } }
/// <summary> /// Gets an Entity Model for a given Entity Identifier. /// </summary> /// <param name="id">The Entity Identifier in format ComponentID-TemplateID.</param> /// <param name="localization">The context Localization.</param> /// <returns>The Entity Model.</returns> /// <exception cref="DxaItemNotFoundException">If no Entity Model exists for the given URL.</exception> /// <remarks> /// Since we can't obtain CT metadata for DCPs, we obtain the View Name from the CT Title. /// </remarks> public virtual EntityModel GetEntityModel(string id, Localization localization) { using (new Tracer(id, localization)) { string[] idParts = id.Split('-'); if (idParts.Length != 2) { throw new DxaException(String.Format("Invalid Entity Identifier '{0}'. Must be in format ComponentID-TemplateID.", id)); } string componentUri = string.Format("tcm:{0}-{1}", localization.LocalizationId, idParts[0]); string templateUri = string.Format("tcm:{0}-{1}-32", localization.LocalizationId, idParts[1]); IComponentPresentationFactory componentPresentationFactory = DD4TFactoryCache.GetComponentPresentationFactory(localization); IComponentPresentation dcp; if (!componentPresentationFactory.TryGetComponentPresentation(out dcp, componentUri, templateUri)) { throw new DxaItemNotFoundException(id); } return(ModelBuilderPipeline.CreateEntityModel(dcp, localization)); } }
/// <summary> /// Gets a Page Model for a given URL. /// </summary> /// <param name="urlPath">The URL path (unescaped).</param> /// <param name="localization">The context Localization.</param> /// <param name="addIncludes">Indicates whether include Pages should be expanded.</param> /// <returns>The Page Model.</returns> /// <exception cref="DxaItemNotFoundException">If no Page Model exists for the given URL.</exception> public virtual PageModel GetPageModel(string urlPath, Localization localization, bool addIncludes) { using (new Tracer(urlPath, localization, addIncludes)) { if (urlPath == null) { urlPath = "/"; } else if (!urlPath.StartsWith("/")) { urlPath = "/" + urlPath; } IPage page = GetPage(urlPath, localization); if (page == null && !urlPath.EndsWith("/")) { // This may be a SG URL path; try if the index page exists. urlPath += Constants.IndexPageUrlSuffix; page = GetPage(urlPath, localization); } else if (urlPath.EndsWith("/")) { urlPath += Constants.DefaultExtensionLessPageName; } if (page == null) { throw new DxaItemNotFoundException(urlPath, localization.Id); } IPage[] includes = addIncludes ? GetIncludesFromModel(page, localization).ToArray() : new IPage[0]; List <string> dependencies = new List <string>() { page.Id }; dependencies.AddRange(includes.Select(p => p.Id)); PageModel result = null; if (CacheRegions.IsViewModelCachingEnabled) { PageModel cachedPageModel = SiteConfiguration.CacheProvider.GetOrAdd( string.Format("{0}:{1}", page.Id, addIncludes), // Cache Page Models with and without includes separately CacheRegions.PageModel, () => { PageModel pageModel = ModelBuilderPipeline.CreatePageModel(page, includes, localization); pageModel.Url = urlPath; if (pageModel.NoCache) { result = pageModel; return(null); } return(pageModel); }, dependencies ); if (cachedPageModel != null) { // Don't return the cached Page Model itself, because we don't want dynamic logic to modify the cached state. result = (PageModel)cachedPageModel.DeepCopy(); } } else { result = ModelBuilderPipeline.CreatePageModel(page, includes, localization); result.Url = urlPath; } if (SiteConfiguration.ConditionalEntityEvaluator != null) { result.FilterConditionalEntities(localization); } return(result); } }
public DefaultContentProvider() { _modelService = new Providers.ModelService.ModelService(); ModelBuilderPipeline.Init(); }
public DefaultContentProvider() { ModelBuilderPipeline.Init(); }
protected virtual RegionModel CreateRegionModel(RegionModelData regionModelData, ILocalization localization) { MvcData mvcData = CreateMvcData(regionModelData.MvcData, "Region"); Type regionModelType = ModelTypeRegistry.GetViewModelType(mvcData); RegionModel result = (RegionModel)regionModelType.CreateInstance(regionModelData.Name); result.ExtensionData = regionModelData.ExtensionData; result.HtmlClasses = regionModelData.HtmlClasses; result.MvcData = mvcData; result.XpmMetadata = localization.IsXpmEnabled ? regionModelData.XpmMetadata : null; result.SchemaId = regionModelData.SchemaId; if (!string.IsNullOrEmpty(regionModelData.SchemaId)) { SemanticSchema semanticSchema = SemanticMapping.GetSchema(regionModelData.SchemaId, localization); Type modelType = ModelTypeRegistry.GetViewModelType(mvcData); MappingData mappingData = new MappingData { SourceViewModel = regionModelData, ModelType = modelType, PropertyValidation = new Validation { MainSchema = semanticSchema, InheritedSchemas = GetInheritedSemanticSchemas(regionModelData, localization) }, Fields = null, MetadataFields = regionModelData.Metadata, Localization = localization }; MapSemanticProperties(result, mappingData); } if (regionModelData.Regions != null) { IEnumerable <RegionModel> nestedRegionModels = regionModelData.Regions.Select(data => CreateRegionModel(data, localization)); result.Regions.UnionWith(nestedRegionModels); result.IsVolatile |= result.Regions.Any(region => region.IsVolatile); } if (regionModelData.Entities != null) { foreach (EntityModelData entityModelData in regionModelData.Entities) { EntityModel entityModel; try { entityModel = ModelBuilderPipeline.CreateEntityModel(entityModelData, null, localization); // indicate to region model that this region is potentially volatile if it contains a volatile entity result.IsVolatile |= entityModel.IsVolatile; entityModel.MvcData.RegionName = regionModelData.Name; } catch (Exception ex) { // If there is a problem mapping an Entity, we replace it with an ExceptionEntity which holds the error details and carry on. Log.Error(ex); entityModel = new ExceptionEntity(ex); } result.Entities.Add(entityModel); } } return(result); }