/// <summary> /// Gets Navigation Links for the context navigation panel for the given request URL path. /// </summary> /// <param name="requestUrlPath">The request URL path.</param> /// <param name="localization">The Localization.</param> /// <returns>The Navigation Links.</returns> public virtual NavigationLinks GetContextNavigationLinks(string requestUrlPath, Localization localization) { using (new Tracer(requestUrlPath, localization)) { // Find the context Sitemap Item; start with Sitemap root. SitemapItem contextSitemapItem = GetNavigationModel(localization); if (requestUrlPath.Contains("/")) { while (contextSitemapItem.Items != null) { SitemapItem matchingChildSg = contextSitemapItem.Items.FirstOrDefault(i => i.Type == SitemapItem.Types.StructureGroup && requestUrlPath.StartsWith(i.Url, StringComparison.InvariantCultureIgnoreCase)); if (matchingChildSg == null) { // No matching child SG found => current contextSitemapItem reflects the context SG. break; } contextSitemapItem = matchingChildSg; } } if (contextSitemapItem.Items == null) { throw new DxaException(string.Format("Context SitemapItem has no child items: {0}", contextSitemapItem)); } return new NavigationLinks { Items = contextSitemapItem.Items.Where(i => i.Visible).Select(i => i.CreateLink(localization)).ToList() }; } }
/// <summary> /// Gets the context claims. Either all context claims or for a given aspect name. /// </summary> /// <param name="aspectName">The aspect name. If <c>null</c> all context claims are returned.</param> /// <param name="localization">The context Localization.</param> /// <returns>A dictionary with the claim names in format aspectName.propertyName as keys.</returns> public IDictionary<string, object> GetContextClaims(string aspectName, Localization localization) { using (new Tracer(aspectName)) { string claimNamePrefix = ContextClaimPrefix; if (!string.IsNullOrEmpty(aspectName)) { claimNamePrefix += aspectName + ":"; } IDictionary<string, object> result = new Dictionary<string, object>(); foreach (KeyValuePair<Uri, object> claim in AmbientDataContext.CurrentClaimStore.GetAll()) { string claimName = claim.Key.ToString(); if (!claimName.StartsWith(claimNamePrefix)) { continue; } string propertyName = claimName.Substring(ContextClaimPrefix.Length).Replace(':', '.'); result.Add(propertyName, claim.Value); } return result; } }
protected override NameValueCollection SetupParameters(SearchQuery searchQuery, Localization localization) { NameValueCollection parameters = base.SetupParameters(searchQuery, localization); // We use the highlighting feature to autogenerate a Summary if no Summary is present in the search index. parameters["hl"] = "true"; return parameters; }
public void BuildEntityModel(ref EntityModel entityModel, IComponentPresentation cp, Localization localization) { using (new Tracer(entityModel, cp, localization)) { IFieldSet contextExpressionsFieldSet; if (cp.ExtensionData == null || !cp.ExtensionData.TryGetValue(Constants.ContextExpressionsKey, out contextExpressionsFieldSet)) { // No Context Expressions found; nothing to do. return; } ContextExpressionConditions conditions = new ContextExpressionConditions(); IField includeField; if (contextExpressionsFieldSet.TryGetValue("Include", out includeField)) { conditions.Include = includeField.Values.ToArray(); } IField excludeField; if (contextExpressionsFieldSet.TryGetValue("Exclude", out excludeField)) { conditions.Exclude = excludeField.Values.ToArray(); } entityModel.SetExtensionData(Constants.ContextExpressionsKey, conditions); } }
/// <summary> /// Gets the rendered XPM markup /// </summary> /// <param name="localization">The context Localization.</param> /// <returns>The XPM markup.</returns> public override string GetXpmMarkup(Localization localization) { if (XpmMetadata == null) { return string.Empty; } string cmsUrl; object cmsUrlValue; if (XpmMetadata.TryGetValue("CmsUrl", out cmsUrlValue)) { cmsUrl = (string) cmsUrlValue; } else { cmsUrl = localization.GetConfigValue("core.cmsurl"); } if (cmsUrl.EndsWith("/")) { // remove trailing slash from cmsUrl if present cmsUrl = cmsUrl.Remove(cmsUrl.Length - 1); } return string.Format( _xpmPageSettingsMarkup, XpmMetadata["PageID"], XpmMetadata["PageModified"], XpmMetadata["PageTemplateID"], XpmMetadata["PageTemplateModified"] ) + string.Format(_xpmPageScript, cmsUrl); }
/// <summary> /// Resolves a link URI (TCM URI or site URL) to a normalized site URL. /// </summary> /// <param name="sourceUri">The source URI (TCM URI or site URL)</param> /// <param name="resolveToBinary">Specifies whether a link to a Multimedia Component should be resolved directly to its Binary (<c>true</c>) or as a regular Component link.</param> /// <param name="localization">The context Localization (optional, since the TCM URI already contains a Publication ID, but this allows resolving in a different context).</param> /// <returns>The resolved URL.</returns> public string ResolveLink(string sourceUri, bool resolveToBinary = false, Localization localization = null) { if (sourceUri == null) { return null; } string url; if (sourceUri.StartsWith("tcm:")) { TcmUri tcmUri = new TcmUri(sourceUri); url = ResolveLink(tcmUri, resolveToBinary, localization); } else { url = sourceUri; } // Strip off default extension / page name if (url != null && url.EndsWith(Constants.DefaultExtension)) { url = url.Substring(0, url.Length - Constants.DefaultExtension.Length); if (url.EndsWith("/" + Constants.DefaultExtensionLessPageName)) { url = url.Substring(0, url.Length - Constants.DefaultExtensionLessPageName.Length); } } return url; }
/// <summary> /// Initializes a new <see cref="CdConfigLocalizationResolver"/> instance. /// </summary> public CdConfigLocalizationResolver() { using (new Tracer()) { string cdDynamicConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\config\cd_dynamic_conf.xml"); XDocument cdDynamicConfigDoc = XDocument.Load(cdDynamicConfigPath); // sorting Publications by Path in decending order so default Path ("/" or "") is last in list // using Path of first Host element found in a Publication, assuming the Paths of all of these Host elements will be equal XElement publicationsElement = cdDynamicConfigDoc.Descendants("Publications").First(); IOrderedEnumerable<XElement> publicationElements = publicationsElement.Elements("Publication").OrderByDescending(e => e.Element("Host").Attribute("Path").Value); foreach (XElement publicationElement in publicationElements) { string publicationId = publicationElement.Attribute("Id").Value; // there could be multiple Host elements per Publication, add them all foreach (XElement hostElement in publicationElement.Elements("Host")) { Uri baseUrl = GetBaseUrl(hostElement); Localization localization; if (!_knownLocalizations.TryGetValue(publicationId, out localization)) { localization = new Localization { LocalizationId = publicationId, Path = hostElement.Attribute("Path").Value }; _knownLocalizations.Add(publicationId, localization); } _urlToLocalizationMapping.Add(new KeyValuePair<Uri, Localization>(baseUrl, localization)); } } } }
static TestFixture() { // TODO: Retrieve Localization Info from CM (?) _parentLocalization = new Localization { LocalizationId = "1065", Path = "/autotest-parent" }; _childLocalization = new Localization { LocalizationId = "1066", Path = "/autotest-child" }; _testLocalizations = new[] { _parentLocalization, _childLocalization }; ArticleDcpEntityId = "9712-9711"; ArticlePageUrlPath = "/autotest-parent/test_article_page.html"; Tsi1278PageUrlPath = "/autotest-parent/tsi-1278_trådløst.html"; Tsi1278StaticContentItemUrlPath = "/autotest-parent/Images/trådløst_tcm1065-9791.jpg"; TestRegistration.RegisterCoreViewModels(); }
/// <summary> /// Determines whether a given Entity Model should be included based on the conditions specified on the Entity Model and the context. /// </summary> /// <param name="entity">The Entity Model to be evaluated.</param> /// <param name="localization">The context Localization</param> /// <returns><c>true</c> if the Entity should be included.</returns> public bool IncludeEntity(EntityModel entity, Localization localization) { using (new Tracer(entity)) { object ceExtensionData; if (entity.ExtensionData == null || !entity.ExtensionData.TryGetValue(Constants.ContextExpressionsKey, out ceExtensionData)) { // No Context Expressions defined for Entity: just include it. return true; } ContextExpressionConditions ceConditions = (ContextExpressionConditions) ceExtensionData; IDictionary<string, object> contextClaims = GetCachedContextClaims(localization); if (!EvaluateContextExpressionClaims(ceConditions.Include, true, contextClaims)) { Log.Debug("Include Context Expression conditions are not satisfied; suppressing Entity [{0}].", entity); return false; } if (!EvaluateContextExpressionClaims(ceConditions.Exclude, false, contextClaims)) { Log.Debug("Exclude Context Expression conditions are not satisfied; suppressing Entity [{0}].", entity); return false; } Log.Debug("All resolved Context Expression conditions are satisfied; keeping Entity [{0}].", entity); return true; } }
private static void ApplyHashIfApplicable(XmlElement linkElement, Localization localization) { string target = linkElement.GetAttribute("target").ToLower(); if (target != "anchored") { return; } string href = linkElement.GetAttribute("href"); bool samePage = string.Equals(href, HttpContext.Current.Request.Url.AbsolutePath, // TODO: should not be using HttpContext at this level StringComparison.OrdinalIgnoreCase ); string linkTitle = GetLinkTitle(linkElement, localization); string fragmentId = string.Empty; if (!string.IsNullOrEmpty(linkTitle)) { fragmentId = '#' + linkTitle.Replace(" ", "_").ToLower(); } linkElement.SetAttribute("href", (!samePage ? href : string.Empty) + fragmentId); linkElement.SetAttribute("target", !samePage ? "_top" : string.Empty); }
/// <summary> /// Gets Navigation Links for the breadcrumb trail for the given request URL path. /// </summary> /// <param name="requestUrlPath">The request URL path.</param> /// <param name="localization">The Localization.</param> /// <returns>The Navigation Links.</returns> public virtual NavigationLinks GetBreadcrumbNavigationLinks(string requestUrlPath, Localization localization) { using (new Tracer(requestUrlPath, localization)) { int levels = requestUrlPath.Split('/').Length; SitemapItem currentItem = GetNavigationModel(localization); // Start with Sitemap root. List<Link> links = new List<Link> { currentItem.CreateLink(localization) }; while (levels > 1 && currentItem.Items != null) { currentItem = currentItem.Items.FirstOrDefault(i => requestUrlPath.StartsWith(i.Url, StringComparison.InvariantCultureIgnoreCase)); if (currentItem == null) { break; } links.Add(currentItem.CreateLink(localization)); levels--; } return new NavigationLinks { Items = links }; } }
/// <summary> /// Resolves a matching <see cref="Localization"/> for a given URL. /// </summary> /// <param name="url">The URL to resolve.</param> /// <returns>A <see cref="Localization"/> instance which base URL matches that of the given URL.</returns> /// <exception cref="DxaUnknownLocalizationException">If no matching Localization can be found.</exception> public override Localization ResolveLocalization(Uri url) { using (new Tracer(url)) { string urlLeftPart = url.GetLeftPart(UriPartial.Path); // TODO PERF: to optimize caching, we could only take the first part of the URL path (e.g. one or two levels) int espaceIndex = urlLeftPart.IndexOf("%"); if (espaceIndex > 0) { // TODO: This is a work-around for a bug in SDL Web 8 Publication Mapping: URLs with escaped characters don't resolve properly (CRQ-1585). // Therefore we truncate the URL at the first escaped character for now (assuming that the URL is still specific enough to resolve the right Publication). urlLeftPart = urlLeftPart.Substring(0, espaceIndex); } IPublicationMapping mapping = null; try { // NOTE: we're not using UrlToLocalizationMapping here, because we may match too eagerly on a base URL when there is a matching mapping with a more specific URL. mapping = _mappingsRetriever.GetPublicationMapping(urlLeftPart); } catch (Exception ex) { // CIL throws Sdl.Web.Delivery.Service.InvalidResourceException if the mapping cannot be resolved. // We don't have a direct reference to Sdl.Web.Delivery.Service, so we just check the type name if (ex.GetType().FullName != "Sdl.Web.Delivery.Service.InvalidResourceException") { throw; } Log.Debug("Exception occurred in DynamicMappingsRetriever.GetPublicationMapping('{0}'):\n{1}", urlLeftPart, ex.ToString()); // Let mapping be null, we'll handle it below. } if (mapping == null || mapping.Port != url.Port.ToString()) // See CRQ-1195 { throw new DxaUnknownLocalizationException(string.Format("No matching Localization found for URL '{0}'", urlLeftPart)); } Localization result; lock (KnownLocalizations) { string localizationId = mapping.PublicationId.ToString(); if (!KnownLocalizations.TryGetValue(localizationId, out result)) { result = new Localization { LocalizationId = localizationId, Path = mapping.Path }; KnownLocalizations.Add(localizationId, result); } } result.EnsureInitialized(); return result; } }
/// <summary> /// Extracts syndication feed items. /// </summary> /// <param name="localization">The context <see cref="Localization"/>.</param> /// <returns>A single syndication feed item containing information extracted from this <see cref="Teaser"/>.</returns> public IEnumerable<SyndicationItem> ExtractSyndicationFeedItems(Localization localization) { Link link = Link; if (link == null && Media != null) { // If the Teaser doesn't have a Link, but does have Media, create a Link from its Media. link = new Link { Url = Media.Url }; } return new[] { CreateSyndicationItem(Headline, Text, link, Date, localization) }; }
/// <summary> /// Initializes a new instance of the <see cref="SchemaSemantics"/> class. /// </summary> /// <param name="prefix">Vocabulary prefix</param> /// <param name="entity">Entity name</param> /// <param name="localization">The context Localization (used to determine <see cref="Vocab"/>).</param> public SchemaSemantics(string prefix, string entity, Localization localization) { Prefix = prefix; Entity = entity; if (localization != null) { Initialize(localization); } }
/// <summary> /// Gets prefix for semantic vocabulary. /// </summary> /// <param name="vocab">Vocabulary name</param> /// <param name="loc">The localization</param> /// <returns>Prefix for this semantic vocabulary</returns> public static string GetPrefix(string vocab, Localization loc) { SemanticVocabulary semanticVocabulary = loc.GetSemanticVocabularies().FirstOrDefault(sv => sv.Vocab == vocab); if (semanticVocabulary == null) { throw new DxaException( string.Format("No vocabulary defined for '{0}' in Localization [{1}]. {2}", vocab, loc, Constants.CheckSettingsUpToDate) ); } return semanticVocabulary.Prefix; }
/// <summary> /// Creates a Strongly Typed Entity Model for a given DD4T Component Presentation. /// </summary> /// <param name="cp">The DD4T Component Presentation.</param> /// <param name="localization">The context <see cref="Localization"/>.</param> /// <returns>The Strongly Typed Entity Model.</returns> public static EntityModel CreateEntityModel(IComponentPresentation cp, Localization localization) { using (new Tracer(cp, localization)) { EntityModel entityModel = null; foreach (IModelBuilder modelBuilder in ModelBuilders) { modelBuilder.BuildEntityModel(ref entityModel, cp, localization); } return entityModel; } }
protected override NameValueCollection SetupParameters(SearchQuery searchQuery, Localization localization) { NameValueCollection result = base.SetupParameters(searchQuery, localization); if (!result.AllKeys.Contains("q.options")) { // By default, limit the search to body, summary and title fields. result["q.options"] = "{ fields: ['body', 'summary', 'title'] }"; } // We use the highlighting feature to autogenerate a Summary if no Summary is present in the search index. result["highlight"] = "{ body: { format: \"text\", max_phrases: 2 } }"; return result; }
/// <summary> /// Creates a <see cref="Link"/> out of this <see cref="SitemapItem"/>. /// </summary> /// <param name="localization">The context <see cref="Localization"/></param> /// <returns>The <see cref="Link"/> Entity Model.</returns> public virtual Link CreateLink(Localization localization) { string linkUrl = Url; if (linkUrl != null && linkUrl.StartsWith("tcm:")) { linkUrl = SiteConfiguration.LinkResolver.ResolveLink(linkUrl); } return new Link { Url = linkUrl, LinkText = Title }; }
/// <summary> /// Processes rich text (XHTML) content. /// </summary> /// <param name="xhtml">The rich text content (XHTML fragment) to be processed.</param> /// <param name="localization">Context localization.</param> /// <returns>The processed rich text content.</returns> /// <remarks> /// Typical rich text processing tasks: /// <list type="bullet"> /// <item>Convert XHTML to plain HTML</item> /// <item>Resolve inline links</item> /// </list> /// </remarks> public RichText ProcessRichText(string xhtml, Localization localization) { try { XmlDocument xhtmlDoc = new XmlDocument(); xhtmlDoc.LoadXml(String.Format("<xhtml>{0}</xhtml>", xhtml)); return ResolveRichText(xhtmlDoc, localization); } catch (XmlException ex) { Log.Warn("An error occurred parsing XHTML fragment; rich text processing is skipped: {0}\nXHTML fragment:\n{1}", ex.Message, xhtml); return new RichText(xhtml); } }
internal static IComponentFactory GetComponentFactory(Localization localization) { lock (_componentFactories) { IComponentFactory componentFactory; if (!_componentFactories.TryGetValue(localization.LocalizationId, out componentFactory)) { componentFactory = new ComponentFactory() { PublicationResolver = new PublicationResolver(localization) }; _componentFactories.Add(localization.LocalizationId, componentFactory); } return componentFactory; } }
internal static IBinaryFactory GetBinaryFactory(Localization localization) { lock (_binaryFactories) { IBinaryFactory binaryFactory; if (!_binaryFactories.TryGetValue(localization.LocalizationId, out binaryFactory)) { binaryFactory = new BinaryFactory() { PublicationResolver = new PublicationResolver(localization) }; _binaryFactories.Add(localization.LocalizationId, binaryFactory); } return binaryFactory; } }
internal static IComponentFactory GetComponentFactory(Localization localization) { lock (_componentFactories) { IComponentFactory componentFactory; if (!_componentFactories.TryGetValue(localization.LocalizationId, out componentFactory)) { IPublicationResolver publicationResolver = new PublicationResolver(localization); IFactoryCommonServices factoryCommonServices = new FactoryCommonServices(publicationResolver, _logger, _config, CreateCacheAgent()); componentFactory = new ComponentFactory( GetComponentPresentationFactory(localization), factoryCommonServices ); _componentFactories.Add(localization.LocalizationId, componentFactory); } return componentFactory; } }
public override Localization GetLocalization(string localizationId) { using (new Tracer(localizationId)) { Localization result; if (!KnownLocalizations.TryGetValue(localizationId, out result)) { // no localization found so lets return a partially constructed one // and fully resolve it later. result = new Localization { LocalizationId = localizationId }; } return result; } }
internal static IPageFactory GetPageFactory(Localization localization) { lock (_pageFactories) { IPageFactory pageFactory; if (!_pageFactories.TryGetValue(localization.LocalizationId, out pageFactory)) { pageFactory = new PageFactory { PublicationResolver = new PublicationResolver(localization), LinkFactory = new ExtensionlessLinkFactory() }; _pageFactories.Add(localization.LocalizationId, pageFactory); } return pageFactory; } }
/// <summary> /// Gets Navigation Links for the breadcrumb trail for the given request URL path. /// </summary> /// <param name="requestUrlPath">The request URL path.</param> /// <param name="localization">The Localization.</param> /// <returns>The Navigation Links.</returns> public NavigationLinks GetBreadcrumbNavigationLinks(string requestUrlPath, Localization localization) { using (new Tracer(requestUrlPath, localization)) { SitemapItem navModel = GetNavigationModel(localization); if (!(navModel is TaxonomyNode)) { // No Navigation Taxonomy found in this Localization; fallback to the StaticNavigationProvider. return _fallbackNavigationProvider.GetBreadcrumbNavigationLinks(requestUrlPath, localization); } SitemapItem sitemapItem = navModel.FindSitemapItem(requestUrlPath.NormalizePageUrlPath()); List<Link> breadcrumb = new List<Link>(); if (sitemapItem != null) { // Build a breadcrumb of ancestors, excluding the Taxonomy Root. bool hasHome = false; while (sitemapItem.Parent != null) { breadcrumb.Insert(0, sitemapItem.CreateLink(localization)); hasHome = IsHome(sitemapItem, localization); sitemapItem = sitemapItem.Parent; } // The Home TaxonomyNode/Keyword may be a top-level sibling instead of an ancestor if (!hasHome) { SitemapItem home = sitemapItem.Items.FirstOrDefault(i => IsHome(i, localization)); if (home != null) { breadcrumb.Insert(0, home.CreateLink(localization)); } } } return new NavigationLinks { Items = breadcrumb }; } }
internal static IBinaryFactory GetBinaryFactory(Localization localization) { lock (_binaryFactories) { IBinaryFactory binaryFactory; if (!_binaryFactories.TryGetValue(localization.LocalizationId, out binaryFactory)) { IPublicationResolver publicationResolver = new PublicationResolver(localization); IProvidersCommonServices providersCommonServices = new ProvidersCommonServices(publicationResolver, _logger, _config); IFactoryCommonServices factoryCommonServices = new FactoryCommonServices(publicationResolver, _logger, _config, CreateCacheAgent()); binaryFactory = new BinaryFactory( new TridionBinaryProvider(providersCommonServices), factoryCommonServices); _binaryFactories.Add(localization.LocalizationId, binaryFactory); } return binaryFactory; } }
static TestFixture() { // TODO: Retrieve Localization Info from CM (?) _parentLocalization = new Localization { LocalizationId = "1065", Path = "/autotest-parent" }; _childLocalization = new Localization { LocalizationId = "1078", Path = "/autotest-child" }; _testLocalizations = new[] { _parentLocalization, _childLocalization }; TestRegistration.RegisterViewModels(); }
private static string ResolveLink(TcmUri tcmUri, bool resolveToBinary, Localization localization) { int localizationId = (localization == null) ? 0 : Convert.ToInt32(localization.LocalizationId); switch ((ItemType)tcmUri.ItemTypeId) { case ItemType.Page: return ResolvePageLink(tcmUri, localizationId); case ItemType.Component: // If requested (resolveToBinary = true), try to resolve Binary Link first. string binaryLink = null; if (resolveToBinary) { binaryLink = ResolveBinaryLink(tcmUri, localizationId); } return binaryLink ?? ResolveComponentLink(tcmUri, localizationId); default: throw new DxaException("Unexpected item type in TCM URI: " + tcmUri); } }
internal static IPageFactory GetPageFactory(Localization localization) { lock (_pageFactories) { IPageFactory pageFactory; if (!_pageFactories.TryGetValue(localization.LocalizationId, out pageFactory)) { IPublicationResolver publicationResolver = new PublicationResolver(localization); IProvidersCommonServices providersCommonServices = new ProvidersCommonServices(publicationResolver, _logger, _config); IFactoryCommonServices factoryCommonServices = new FactoryCommonServices(publicationResolver, _logger, _config, CreateCacheAgent()); pageFactory = new PageFactory( new TridionPageProvider(providersCommonServices), GetComponentPresentationFactory(localization), factoryCommonServices ); _pageFactories.Add(localization.LocalizationId, pageFactory); } return pageFactory; } }
/// <summary> /// Initializes an existing instance. /// </summary> /// <param name="localization">The context Localization.</param> public void Initialize(Localization localization) { Localization = localization; foreach (SchemaSemantics semantics in Semantics) { semantics.Initialize(localization); } foreach (SemanticSchemaField field in Fields) { field.Initialize(localization); } }