// TODO: (core) Apply IDisplayedEntity to BlogPostTag public static string BuildSlug <T>(this T entity, int?languageId = null) where T : IDisplayedEntity { Guard.NotNull(entity, nameof(entity)); var name = entity.GetDisplayName(); if (entity is ILocalizedEntity le) { name = le.GetLocalized(entity.GetDisplayNameMemberName(), name, languageId); } return(SeoHelper.BuildSlug(name)); }
public virtual async ValueTask <ValidateSlugResult> ValidateSlugAsync <T>(T entity, string seName, bool ensureNotEmpty, int?languageId = null) where T : ISlugSupported { Guard.NotNull(entity, nameof(entity)); var displayName = entity.GetDisplayName(); var entityName = entity.GetEntityName(); // Use entity DisplayName if seName is not specified if (string.IsNullOrWhiteSpace(seName) && !string.IsNullOrWhiteSpace(displayName)) { seName = displayName; } // Validation var slug = SeoHelper.BuildSlug(seName, _seoSettings.ConvertNonWesternChars, _seoSettings.AllowUnicodeCharsInUrls, true, _seoSettings.SeoNameCharConversion); if (string.IsNullOrWhiteSpace(slug)) { if (ensureNotEmpty) { // Use entity identifier as slug if empty slug = entityName.ToLower() + entity.Id.ToStringInvariant(); } else { // Return. no need for further processing return(new ValidateSlugResult { Source = entity, Slug = slug, LanguageId = languageId, WasValidated = true }); } } // Validate and alter slug if it could be interpreted as SEO code if (CultureHelper.IsValidCultureCode(slug)) { if (seName.Length == 2) { slug += "-0"; } } // Ensure this slug is not reserved int i = 2; string tempSlug = slug; UrlRecord found = null; bool foundIsSelf = false; while (true) { // Check whether such slug already exists in the database var urlRecord = _extraSlugLookup.Get(tempSlug) ?? (await _db.UrlRecords.FirstOrDefaultAsync(x => x.Slug == tempSlug)); // Check whether found record refers to requested entity foundIsSelf = FoundRecordIsSelf(entity, urlRecord, languageId); // ...and it's not in the list of reserved slugs var reserved = _seoSettings.ReservedUrlRecordSlugs.Contains(tempSlug); if ((urlRecord == null || foundIsSelf) && !reserved) { found = urlRecord; break; } // Try again with unique index appended var suffixLen = Math.Floor(Math.Log10(i) + 1).Convert <int>() + 1; tempSlug = string.Format("{0}-{1}", slug.Truncate(400 - suffixLen), i); found = urlRecord; i++; } slug = tempSlug; return(new ValidateSlugResult { Source = entity, Slug = slug, Found = found, FoundIsSelf = foundIsSelf, LanguageId = languageId, WasValidated = true }); }