/// <summary> /// Creates the full link expression including type, value and query string. /// </summary> /// <param name="includeQueryString">Whether to include the query string.</param> /// <returns>Link expression.</returns> public static string CreateExpression(this LinkResolverResult data, bool includeQueryString = true) { if (data?.Value == null) { return(string.Empty); } var result = data.Type == LinkType.Url ? data.Value.ToString() : string.Concat(data.Type.ToString().ToLower(), ":", data.Value.ToString()); if (includeQueryString && data.Type != LinkType.Url && !string.IsNullOrWhiteSpace(data.QueryString)) { return(string.Concat(result, "?", data.QueryString)); } return(result); }
public virtual LinkResolverResult Resolve(string linkExpression, IEnumerable <CustomerRole> roles = null, int languageId = 0, int storeId = 0) { if (linkExpression.IsEmpty()) { return(new LinkResolverResult { Type = LinkType.Url, Status = LinkStatus.NotFound }); } if (roles == null) { roles = _services.WorkContext.CurrentCustomer.CustomerRoles; } if (languageId == 0) { languageId = _services.WorkContext.WorkingLanguage.Id; } if (storeId == 0) { storeId = _services.StoreContext.CurrentStore.Id; } var d = Parse(linkExpression); var queryString = d.QueryString; if (d.Type == LinkType.Url) { var url = d.Value.ToString(); if (url.EmptyNull().StartsWith("~")) { url = VirtualPathUtility.ToAbsolute(url); } d.Link = d.Label = url; } else if (d.Type == LinkType.File) { d.Link = d.Label = d.Value.ToString(); } else { var cacheKey = LINKRESOLVER_KEY.FormatInvariant( d.Expression.EmptyNull().ToLower(), languageId, storeId, string.Join(",", roles.Where(x => x.Active).Select(x => x.Id))); d = _services.Cache.Get(cacheKey, () => { var d2 = d.Clone(); switch (d2.Type) { case LinkType.Product: GetEntityData <Product>(d2, languageId, x => new ResolverEntitySummary { Name = x.Name, Published = x.Published, Deleted = x.Deleted, SubjectToAcl = x.SubjectToAcl, LimitedToStores = x.LimitedToStores, PictureId = x.MainPictureId }); break; case LinkType.Category: GetEntityData <Category>(d2, languageId, x => new ResolverEntitySummary { Name = x.Name, Published = x.Published, Deleted = x.Deleted, SubjectToAcl = x.SubjectToAcl, LimitedToStores = x.LimitedToStores, PictureId = x.PictureId }); break; case LinkType.Manufacturer: GetEntityData <Manufacturer>(d2, languageId, x => new ResolverEntitySummary { Name = x.Name, Published = x.Published, Deleted = x.Deleted, LimitedToStores = x.LimitedToStores, PictureId = x.PictureId }); break; case LinkType.Topic: GetEntityData <Topic>(d2, languageId, x => null); break; default: throw new SmartException("Unknown link builder type."); } return(d2); }); } var result = new LinkResolverResult { Type = d.Type, Status = d.Status, Value = d.Value, Link = d.Link, QueryString = queryString, Label = d.Label, Id = d.Id, PictureId = d.PictureId }; // Check ACL and limited to stores. switch (d.Type) { case LinkType.Product: case LinkType.Category: case LinkType.Manufacturer: case LinkType.Topic: var entityName = d.Type.ToString(); if (d.LimitedToStores && d.Status == LinkStatus.Ok && !QuerySettings.IgnoreMultiStore && !_storeMappingService.Authorize(entityName, d.Id, storeId)) { result.Status = LinkStatus.NotFound; } else if (d.SubjectToAcl && d.Status == LinkStatus.Ok && !QuerySettings.IgnoreAcl && !_aclService.Authorize(entityName, d.Id, roles)) { result.Status = LinkStatus.Forbidden; } break; } return(result); }