diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs index d83438ab06..db6470e3cc 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs @@ -5,31 +5,10 @@ /// public interface IPublishedValueFallback { - /// - /// Gets a value. - /// - /// - /// This is invoked when getting a value for the specified and - /// could not return a value, and fallback rules should apply to get the value for another language and/or segment. - /// - TValue GetValue(IPublishedProperty property, string culture, string segment); - } + // todo - define & implement - // fixme question - // this is working at property level at the moment, should we move it up to element, - // so that the decision can be made based upon the entire element, other properties, etc? - // or, would we need the *two* levels? - - /// - /// Provides a default implementation of that does not fall back at all. - /// - public class NoPublishedValueFallback : IPublishedValueFallback - { - /// - public TValue GetValue(IPublishedProperty property, string culture, string segment) - { - // we don't implement fallback - return default; - } + // property level ... should we move it up to element, + // so that the decision can be made based upon the entire element, other properties, etc? + // or, would we need the *two* levels? } } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedCultureInfos.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedCultureInfos.cs index 2522f0366f..3f9f7e9882 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedCultureInfos.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedCultureInfos.cs @@ -43,9 +43,9 @@ namespace Umbraco.Core.Models.PublishedContent /// /// /// A published content item will only have published cultures, and therefore this - /// value will always be true. On the other hand, fixme drafts? + /// value will always be true. On the other hand, ... ??? /// - public bool Published { get; } + public bool Published { get; } // fixme - what is culture.Published? /// /// Gets the date associated with the culture. diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index cded44a7e9..d894af47ee 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -1111,7 +1111,7 @@ namespace Umbraco.Core /// The text to filter. /// The culture. /// The safe alias. - public static string ToSafeAlias(this string alias, CultureInfo culture) + public static string ToSafeAlias(this string alias, string culture) { return Current.ShortStringHelper.CleanStringForSafeAlias(alias, culture); } @@ -1134,7 +1134,7 @@ namespace Umbraco.Core /// The culture. /// The safe alias. /// Checks UmbracoSettings.ForceSafeAliases to determine whether it should filter the text. - public static string ToSafeAliasWithForcingCheck(this string alias, CultureInfo culture) + public static string ToSafeAliasWithForcingCheck(this string alias, string culture) { return UmbracoConfig.For.UmbracoSettings().Content.ForceSafeAliases ? alias.ToSafeAlias(culture) : alias; } @@ -1158,20 +1158,8 @@ namespace Umbraco.Core /// The culture. /// The safe url segment. public static string ToUrlSegment(this string text, string culture) - => text.ToUrlSegment(CultureInfo.GetCultureInfo(culture)); + => Current.ShortStringHelper.CleanStringForUrlSegment(text, culture); - /// - /// Cleans a string, in the context of a specified culture, to produce a string that can safely be used in an url segment. - /// - /// The text to filter. - /// The culture. - /// The safe url segment. - // todo: obsolete that one and use the string one (requires changes to IShortStringHelper) - public static string ToUrlSegment(this string text, CultureInfo culture) - { - return Current.ShortStringHelper.CleanStringForUrlSegment(text, culture); - } - // the new methods to clean a string (to alias, url segment...) /// @@ -1209,7 +1197,7 @@ namespace Umbraco.Core /// strings are cleaned up to camelCase and Ascii. /// The culture. /// The clean string. - public static string ToCleanString(this string text, CleanStringType stringType, CultureInfo culture) + public static string ToCleanString(this string text, CleanStringType stringType, string culture) { return Current.ShortStringHelper.CleanString(text, stringType, culture); } @@ -1223,7 +1211,7 @@ namespace Umbraco.Core /// The separator. /// The culture. /// The clean string. - public static string ToCleanString(this string text, CleanStringType stringType, char separator, CultureInfo culture) + public static string ToCleanString(this string text, CleanStringType stringType, char separator, string culture) { return Current.ShortStringHelper.CleanString(text, stringType, separator, culture); } @@ -1269,7 +1257,7 @@ namespace Umbraco.Core /// The text to filter. /// The culture. /// The safe filename. - public static string ToSafeFileName(this string text, CultureInfo culture) + public static string ToSafeFileName(this string text, string culture) { return Current.ShortStringHelper.CleanStringForSafeFileName(text, culture); } diff --git a/src/Umbraco.Core/Strings/ContentBaseExtensions.cs b/src/Umbraco.Core/Strings/ContentBaseExtensions.cs index 29ef235f2b..1ae43b96e6 100644 --- a/src/Umbraco.Core/Strings/ContentBaseExtensions.cs +++ b/src/Umbraco.Core/Strings/ContentBaseExtensions.cs @@ -11,23 +11,6 @@ namespace Umbraco.Core.Strings /// internal static class ContentBaseExtensions { - - /// - /// Gets the default url segment for a specified content. - /// - /// The content. - /// - /// The url segment. - public static string GetUrlSegment(this IContentBase content, IEnumerable urlSegmentProviders) - { - if (content == null) throw new ArgumentNullException("content"); - if (urlSegmentProviders == null) throw new ArgumentNullException("urlSegmentProviders"); - - var url = urlSegmentProviders.Select(p => p.GetUrlSegment(content)).FirstOrDefault(u => u != null); - url = url ?? new DefaultUrlSegmentProvider().GetUrlSegment(content); // be safe - return url; - } - /// /// Gets the url segment for a specified content and culture. /// @@ -35,11 +18,11 @@ namespace Umbraco.Core.Strings /// The culture. /// /// The url segment. - public static string GetUrlSegment(this IContentBase content, CultureInfo culture, IEnumerable urlSegmentProviders) + public static string GetUrlSegment(this IContentBase content, IEnumerable urlSegmentProviders, string culture = null) { - if (content == null) throw new ArgumentNullException("content"); - if (culture == null) throw new ArgumentNullException("culture"); - if (urlSegmentProviders == null) throw new ArgumentNullException("urlSegmentProviders"); + if (content == null) throw new ArgumentNullException(nameof(content)); + if (culture == null) throw new ArgumentNullException(nameof(culture)); + if (urlSegmentProviders == null) throw new ArgumentNullException(nameof(urlSegmentProviders)); var url = urlSegmentProviders.Select(p => p.GetUrlSegment(content, culture)).FirstOrDefault(u => u != null); url = url ?? new DefaultUrlSegmentProvider().GetUrlSegment(content, culture); // be safe diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index 3a9d9433f4..d587893d99 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -18,7 +17,7 @@ namespace Umbraco.Core.Strings /// public class DefaultShortStringHelper : IShortStringHelper { - #region Ctor and vars + #region Ctor, consts and vars public DefaultShortStringHelper(IUmbracoSettingsSection settings) { @@ -31,6 +30,8 @@ namespace Umbraco.Core.Strings _config = config.Clone(); } + public const string InvariantCulture = "xx-xx"; + // see notes for CleanAsciiString //// beware! the order is quite important here! //const string ValidStringCharactersSource = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -138,7 +139,7 @@ function validateSafeAlias(input, value, immediate, callback) {{ /// /// Safe aliases are Ascii only. /// - public virtual string CleanStringForSafeAlias(string text, CultureInfo culture) + public virtual string CleanStringForSafeAlias(string text, string culture) { return CleanString(text, CleanStringType.Alias, culture); } @@ -166,7 +167,7 @@ function validateSafeAlias(input, value, immediate, callback) {{ /// /// Url segments are Ascii only (no accents...). /// - public virtual string CleanStringForUrlSegment(string text, CultureInfo culture) + public virtual string CleanStringForUrlSegment(string text, string culture) { return CleanString(text, CleanStringType.UrlSegment, culture); } @@ -190,11 +191,12 @@ function validateSafeAlias(input, value, immediate, callback) {{ /// The text to filter. /// The culture. /// The safe filename. - public virtual string CleanStringForSafeFileName(string text, CultureInfo culture) + public virtual string CleanStringForSafeFileName(string text, string culture) { if (string.IsNullOrWhiteSpace(text)) return string.Empty; + culture = culture ?? InvariantCulture; text = text.ReplaceMany(Path.GetInvalidFileNameChars(), '-'); var name = Path.GetFileNameWithoutExtension(text); @@ -266,7 +268,7 @@ function validateSafeAlias(input, value, immediate, callback) {{ /// strings are cleaned up to camelCase and Ascii. /// The culture. /// The clean string. - public string CleanString(string text, CleanStringType stringType, CultureInfo culture) + public string CleanString(string text, CleanStringType stringType, string culture) { return CleanString(text, stringType, culture, null); } @@ -280,16 +282,16 @@ function validateSafeAlias(input, value, immediate, callback) {{ /// The separator. /// The culture. /// The clean string. - public string CleanString(string text, CleanStringType stringType, char separator, CultureInfo culture) + public string CleanString(string text, CleanStringType stringType, char separator, string culture) { return CleanString(text, stringType, culture, separator); } - protected virtual string CleanString(string text, CleanStringType stringType, CultureInfo culture, char? separator) + protected virtual string CleanString(string text, CleanStringType stringType, string culture, char? separator) { // be safe if (text == null) throw new ArgumentNullException(nameof(text)); - if (culture == null) throw new ArgumentNullException(nameof(culture)); + culture = culture ?? InvariantCulture; // get config var config = _config.For(stringType, culture); @@ -367,11 +369,12 @@ function validateSafeAlias(input, value, immediate, callback) {{ // that the utf8 version. Micro-optimizing sometimes isn't such a good idea. // note: does NOT support surrogate pairs in text - internal string CleanCodeString(string text, CleanStringType caseType, char separator, CultureInfo culture, DefaultShortStringHelperConfig.Config config) + internal string CleanCodeString(string text, CleanStringType caseType, char separator, string culture, DefaultShortStringHelperConfig.Config config) { int opos = 0, ipos = 0; var state = StateBreak; + culture = culture ?? InvariantCulture; caseType &= CleanStringType.CaseMask; // if we apply global ToUpper or ToLower to text here @@ -501,9 +504,10 @@ function validateSafeAlias(input, value, immediate, callback) {{ // note: supports surrogate pairs in input string internal void CopyTerm(string input, int ipos, char[] output, ref int opos, int len, - CleanStringType caseType, CultureInfo culture, bool isAcronym) + CleanStringType caseType, string culture, bool isAcronym) { var term = input.Substring(ipos, len); + var cultureInfo = culture == null || culture == InvariantCulture ? CultureInfo.InvariantCulture : CultureInfo.GetCultureInfo(culture); if (isAcronym) { @@ -529,13 +533,13 @@ function validateSafeAlias(input, value, immediate, callback) {{ break; case CleanStringType.LowerCase: - term = term.ToLower(culture); + term = term.ToLower(cultureInfo); term.CopyTo(0, output, opos, term.Length); opos += term.Length; break; case CleanStringType.UpperCase: - term = term.ToUpper(culture); + term = term.ToUpper(cultureInfo); term.CopyTo(0, output, opos, term.Length); opos += term.Length; break; @@ -546,18 +550,18 @@ function validateSafeAlias(input, value, immediate, callback) {{ if (char.IsSurrogate(c)) { s = term.Substring(ipos, 2); - s = opos == 0 ? s.ToLower(culture) : s.ToUpper(culture); + s = opos == 0 ? s.ToLower(cultureInfo) : s.ToUpper(cultureInfo); s.CopyTo(0, output, opos, s.Length); opos += s.Length; i++; // surrogate pair len is 2 } else { - output[opos] = opos++ == 0 ? char.ToLower(c, culture) : char.ToUpper(c, culture); + output[opos] = opos++ == 0 ? char.ToLower(c, cultureInfo) : char.ToUpper(c, cultureInfo); } if (len > i) { - term = term.Substring(i).ToLower(culture); + term = term.Substring(i).ToLower(cultureInfo); term.CopyTo(0, output, opos, term.Length); opos += term.Length; } @@ -569,18 +573,18 @@ function validateSafeAlias(input, value, immediate, callback) {{ if (char.IsSurrogate(c)) { s = term.Substring(ipos, 2); - s = s.ToUpper(culture); + s = s.ToUpper(cultureInfo); s.CopyTo(0, output, opos, s.Length); opos += s.Length; i++; // surrogate pair len is 2 } else { - output[opos++] = char.ToUpper(c, culture); + output[opos++] = char.ToUpper(c, cultureInfo); } if (len > i) { - term = term.Substring(i).ToLower(culture); + term = term.Substring(i).ToLower(cultureInfo); term.CopyTo(0, output, opos, term.Length); opos += term.Length; } @@ -592,14 +596,14 @@ function validateSafeAlias(input, value, immediate, callback) {{ if (char.IsSurrogate(c)) { s = term.Substring(ipos, 2); - s = opos == 0 ? s : s.ToUpper(culture); + s = opos == 0 ? s : s.ToUpper(cultureInfo); s.CopyTo(0, output, opos, s.Length); opos += s.Length; i++; // surrogate pair len is 2 } else { - output[opos] = opos++ == 0 ? c : char.ToUpper(c, culture); + output[opos] = opos++ == 0 ? c : char.ToUpper(c, cultureInfo); } if (len > i) { @@ -668,8 +672,6 @@ function validateSafeAlias(input, value, immediate, callback) {{ return new string(output, 0, opos); } - #endregion - - + #endregion } } diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs index 8a6aca632b..7c61175836 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Umbraco.Core.Configuration.UmbracoSettings; @@ -8,7 +7,7 @@ namespace Umbraco.Core.Strings { public class DefaultShortStringHelperConfig { - private readonly Dictionary> _configs = new Dictionary>(); + private readonly Dictionary> _configs = new Dictionary>(); public DefaultShortStringHelperConfig Clone() { @@ -29,7 +28,7 @@ namespace Umbraco.Core.Strings return config; } - public CultureInfo DefaultCulture { get; set; } = CultureInfo.InvariantCulture; + public string DefaultCulture { get; set; } = DefaultShortStringHelper.InvariantCulture; public Dictionary UrlReplaceCharacters { get; set; } @@ -45,10 +44,12 @@ namespace Umbraco.Core.Strings return WithConfig(DefaultCulture, stringRole, config); } - public DefaultShortStringHelperConfig WithConfig(CultureInfo culture, CleanStringType stringRole, Config config) + public DefaultShortStringHelperConfig WithConfig(string culture, CleanStringType stringRole, Config config) { if (config == null) throw new ArgumentNullException(nameof(config)); + culture = culture ?? DefaultShortStringHelper.InvariantCulture; + if (_configs.ContainsKey(culture) == false) _configs[culture] = new Dictionary(); _configs[culture][stringRole] = config; @@ -112,8 +113,9 @@ namespace Umbraco.Core.Strings // internal: we don't want ppl to retrieve a config and modify it // (the helper uses a private clone to prevent modifications) - internal Config For(CleanStringType stringType, CultureInfo culture) + internal Config For(CleanStringType stringType, string culture) { + culture = culture ?? DefaultShortStringHelper.InvariantCulture; stringType = stringType & CleanStringType.RoleMask; Dictionary config; diff --git a/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs b/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs index d2e47e04b4..87a6bccd13 100644 --- a/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs +++ b/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using Umbraco.Core.Models; +using Umbraco.Core.Models; namespace Umbraco.Core.Strings { @@ -8,23 +7,13 @@ namespace Umbraco.Core.Strings /// public class DefaultUrlSegmentProvider : IUrlSegmentProvider { - /// - /// Gets the default url segment for a specified content. - /// - /// The content. - /// The url segment. - public string GetUrlSegment(IContentBase content) - { - return GetUrlSegmentSource(content).ToUrlSegment(); - } - /// /// Gets the url segment for a specified content and culture. /// /// The content. /// The culture. /// The url segment. - public string GetUrlSegment(IContentBase content, CultureInfo culture) + public string GetUrlSegment(IContentBase content, string culture = null) { return GetUrlSegmentSource(content).ToUrlSegment(culture); } diff --git a/src/Umbraco.Core/Strings/IShortStringHelper.cs b/src/Umbraco.Core/Strings/IShortStringHelper.cs index 7232b0efe7..afe2166330 100644 --- a/src/Umbraco.Core/Strings/IShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/IShortStringHelper.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Globalization; - -namespace Umbraco.Core.Strings +namespace Umbraco.Core.Strings { /// /// Provides string functions for short strings such as aliases or url segments. @@ -31,7 +28,7 @@ namespace Umbraco.Core.Strings /// The text to filter. /// The culture. /// The safe alias. - string CleanStringForSafeAlias(string text, CultureInfo culture); + string CleanStringForSafeAlias(string text, string culture); /// /// Cleans a string to produce a string that can safely be used in an url segment. @@ -47,7 +44,7 @@ namespace Umbraco.Core.Strings /// The text to filter. /// The culture. /// The safe url segment. - string CleanStringForUrlSegment(string text, CultureInfo culture); + string CleanStringForUrlSegment(string text, string culture); /// /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used as a filename, @@ -66,7 +63,7 @@ namespace Umbraco.Core.Strings /// The culture. /// The safe filename. /// Legacy says this was used to "overcome an issue when Umbraco is used in IE in an intranet environment" but that issue is not documented. - string CleanStringForSafeFileName(string text, CultureInfo culture); + string CleanStringForSafeFileName(string text, string culture); /// /// Splits a pascal-cased string by inserting a separator in between each term. @@ -106,7 +103,7 @@ namespace Umbraco.Core.Strings /// strings are cleaned up to camelCase and Ascii. /// The culture. /// The clean string. - string CleanString(string text, CleanStringType stringType, CultureInfo culture); + string CleanString(string text, CleanStringType stringType, string culture); /// /// Cleans a string in the context of a specified culture, using a specified separator. @@ -117,6 +114,6 @@ namespace Umbraco.Core.Strings /// The separator. /// The culture. /// The clean string. - string CleanString(string text, CleanStringType stringType, char separator, CultureInfo culture); + string CleanString(string text, CleanStringType stringType, char separator, string culture); } } diff --git a/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs b/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs index 4674361b95..1acbcea769 100644 --- a/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs +++ b/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs @@ -9,13 +9,6 @@ namespace Umbraco.Core.Strings /// Url segments should comply with IETF RFCs regarding content, encoding, etc. public interface IUrlSegmentProvider { - /// - /// Gets the default url segment for a specified content. - /// - /// The content. - /// The url segment. - string GetUrlSegment(IContentBase content); // fixme do we need to have both? - /// /// Gets the url segment for a specified content and culture. /// @@ -25,7 +18,7 @@ namespace Umbraco.Core.Strings /// This is for when Umbraco is capable of managing more than one url /// per content, in 1-to-1 multilingual configurations. Then there would be one /// url per culture. - string GetUrlSegment(IContentBase content, CultureInfo culture); + string GetUrlSegment(IContentBase content, string culture = null); //TODO: For the 301 tracking, we need to add another extended interface to this so that // the RedirectTrackingEventHandler can ask the IUrlSegmentProvider if the URL is changing. diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 1068ba3243..516fdbdd0e 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.XmlPublishedCache; @@ -78,7 +79,7 @@ namespace Umbraco.Tests.Cache.PublishedCache umbracoSettings, Enumerable.Empty(), globalSettings, - ServiceContext.EntityService); + new TestCurrentVariationAccessor()); _cache = _umbracoContext.ContentCache; } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 465034db05..8a465a1da8 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -18,6 +18,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using Umbraco.Tests.Testing.Objects.Accessors; namespace Umbraco.Tests.PublishedContent { @@ -74,8 +75,8 @@ namespace Umbraco.Tests.PublishedContent new WebSecurity(httpContext, Current.Services.UserService, globalSettings), TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - globalSettings, - ServiceContext.EntityService); + globalSettings, + new TestCurrentVariationAccessor()); return umbracoContext; } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 2cf555efda..2816af7a90 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -324,8 +324,8 @@ namespace Umbraco.Tests.PublishedContent public void GetPropertyValueRecursiveTest() { var doc = GetNode(1174); - var rVal = doc.Value("testRecursive", true); - var nullVal = doc.Value("DoNotFindThis", true); + var rVal = doc.Value("testRecursive", recurse: true); + var nullVal = doc.Value("DoNotFindThis", recurse: true); Assert.AreEqual("This is the recursive val", rVal); Assert.AreEqual(null, nullVal); } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index b6eff1e0ef..c1be083c38 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -21,6 +21,7 @@ using Umbraco.Core.Services.Implement; using Umbraco.Core.Sync; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.Cache; using Umbraco.Web.PublishedCache; @@ -113,7 +114,7 @@ namespace Umbraco.Tests.Scoping umbracoSettings ?? SettingsForTests.GetDefaultUmbracoSettings(), urlProviders ?? Enumerable.Empty(), globalSettings, - Mock.Of()); + new TestCurrentVariationAccessor()); if (setSingleton) Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs index 51d6a7fa7d..49b4f3f5aa 100644 --- a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs @@ -9,6 +9,7 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Services; using Umbraco.Tests.Testing; +using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -33,7 +34,7 @@ namespace Umbraco.Tests.Security Mock.Of(), new WebSecurity(Mock.Of(), Current.Services.UserService, globalSettings), TestObjects.GetUmbracoSettings(), new List(),globalSettings, - Mock.Of()); + new TestCurrentVariationAccessor()); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Install); var mgr = new BackOfficeCookieManager( @@ -53,7 +54,7 @@ namespace Umbraco.Tests.Security Mock.Of(), new WebSecurity(Mock.Of(), Current.Services.UserService, globalSettings), TestObjects.GetUmbracoSettings(), new List(), globalSettings, - Mock.Of()); + new TestCurrentVariationAccessor()); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx), runtime, TestObjects.GetGlobalSettings()); diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 543b4133f9..36e5874e14 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -43,7 +43,7 @@ namespace Umbraco.Tests.Strings StringType = CleanStringType.LowerCase | CleanStringType.Ascii, Separator = '-' }) - .WithConfig(new CultureInfo("fr-FR"), CleanStringType.UrlSegment, new DefaultShortStringHelperConfig.Config + .WithConfig("fr-FR", CleanStringType.UrlSegment, new DefaultShortStringHelperConfig.Config { PreFilter = FilterFrenchElisions, IsTerm = (c, leading) => leading ? char.IsLetter(c) : (char.IsLetterOrDigit(c) || c == '_'), @@ -56,7 +56,7 @@ namespace Umbraco.Tests.Strings IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), StringType = CleanStringType.UmbracoCase | CleanStringType.Ascii }) - .WithConfig(new CultureInfo("fr-FR"), CleanStringType.Alias, new DefaultShortStringHelperConfig.Config + .WithConfig("fr-FR", CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { PreFilter = WhiteQuotes, IsTerm = (c, leading) => leading ? char.IsLetter(c) : char.IsLetterOrDigit(c), @@ -588,16 +588,12 @@ namespace Umbraco.Tests.Strings #endregion public void CleanStringWithTypeAndCulture(string input, string expected, string culture, CleanStringType stringType) { - var cinfo = culture == null ? CultureInfo.InvariantCulture : new CultureInfo(culture); - // picks the proper config per culture // and overrides some stringType params (ascii...) - var output = _helper.CleanString(input, stringType, cinfo); + var output = _helper.CleanString(input, stringType, culture); Assert.AreEqual(expected, output); } - - #region Cases [TestCase("foo.txt", "foo.txt")] [TestCase("foo", "foo")] diff --git a/src/Umbraco.Tests/Strings/MockShortStringHelper.cs b/src/Umbraco.Tests/Strings/MockShortStringHelper.cs index 964e1d7ad2..e0df7ea4e9 100644 --- a/src/Umbraco.Tests/Strings/MockShortStringHelper.cs +++ b/src/Umbraco.Tests/Strings/MockShortStringHelper.cs @@ -19,17 +19,7 @@ namespace Umbraco.Tests.Strings return "SAFE-ALIAS::" + text; } - public string CleanStringForSafeCamelAlias(string text) - { - return "SAFE-ALIAS::" + text; - } - - public string CleanStringForSafeAlias(string text, System.Globalization.CultureInfo culture) - { - return "SAFE-ALIAS-CULTURE::" + text; - } - - public string CleanStringForSafeCamelAlias(string text, System.Globalization.CultureInfo culture) + public string CleanStringForSafeAlias(string text, string culture) { return "SAFE-ALIAS-CULTURE::" + text; } @@ -39,7 +29,7 @@ namespace Umbraco.Tests.Strings return "URL-SEGMENT::" + text; } - public string CleanStringForUrlSegment(string text, System.Globalization.CultureInfo culture) + public string CleanStringForUrlSegment(string text, string culture) { return "URL-SEGMENT-CULTURE::" + text; } @@ -49,7 +39,7 @@ namespace Umbraco.Tests.Strings return "SAFE-FILE-NAME::" + text; } - public string CleanStringForSafeFileName(string text, System.Globalization.CultureInfo culture) + public string CleanStringForSafeFileName(string text, string culture) { return "SAFE-FILE-NAME-CULTURE::" + text; } @@ -69,12 +59,12 @@ namespace Umbraco.Tests.Strings return "CLEAN-STRING-B::" + text; } - public string CleanString(string text, CleanStringType stringType, System.Globalization.CultureInfo culture) + public string CleanString(string text, CleanStringType stringType, string culture) { return "CLEAN-STRING-C::" + text; } - public string CleanString(string text, CleanStringType stringType, char separator, System.Globalization.CultureInfo culture) + public string CleanString(string text, CleanStringType stringType, char separator, string culture) { return "CLEAN-STRING-D::" + text; } diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs index b297f27656..55976e0d89 100644 --- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -188,7 +188,7 @@ namespace Umbraco.Tests.Strings [Test] public void ToSafeAliasWithCulture() { - var output = "JUST-ANYTHING".ToSafeAlias(CultureInfo.InvariantCulture); + var output = "JUST-ANYTHING".ToSafeAlias(null); Assert.AreEqual("SAFE-ALIAS-CULTURE::JUST-ANYTHING", output); } @@ -202,7 +202,7 @@ namespace Umbraco.Tests.Strings [Test] public void ToUrlSegmentWithCulture() { - var output = "JUST-ANYTHING".ToUrlSegment(CultureInfo.InvariantCulture); + var output = "JUST-ANYTHING".ToUrlSegment(null); Assert.AreEqual("URL-SEGMENT-CULTURE::JUST-ANYTHING", output); } @@ -216,7 +216,7 @@ namespace Umbraco.Tests.Strings [Test] public void ToSafeFileNameWithCulture() { - var output = "JUST-ANYTHING".ToSafeFileName(CultureInfo.InvariantCulture); + var output = "JUST-ANYTHING".ToSafeFileName(null); Assert.AreEqual("SAFE-FILE-NAME-CULTURE::JUST-ANYTHING", output); } diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index d5f10cc324..6053a1fad3 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -29,6 +29,7 @@ using Umbraco.Web.Security; using Umbraco.Web.WebApi; using LightInject; using System.Globalization; +using Umbraco.Tests.Testing.Objects.Accessors; namespace Umbraco.Tests.TestHelpers.ControllerTesting { @@ -149,7 +150,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == UrlProviderMode.Auto.ToString())), Enumerable.Empty(), globalSettings, - mockedEntityService, + new TestCurrentVariationAccessor(), true); //replace it var urlHelper = new Mock(); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 4952360b6a..4b7fddb337 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -120,7 +120,7 @@ namespace Umbraco.Tests.TestHelpers var urlProviders = Enumerable.Empty(); if (accessor == null) accessor = new TestUmbracoContextAccessor(); - return UmbracoContext.EnsureContext(accessor, httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, Mock.Of(), true); + return UmbracoContext.EnsureContext(accessor, httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, new TestCurrentVariationAccessor(), true); } public IUmbracoSettingsSection GetUmbracoSettings() diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 2c2b275e7f..b08376fe8a 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -379,7 +379,7 @@ namespace Umbraco.Tests.TestHelpers umbracoSettings ?? Container.GetInstance(), urlProviders ?? Enumerable.Empty(), globalSettings ?? Container.GetInstance(), - ServiceContext.EntityService); + new TestCurrentVariationAccessor()); if (setSingleton) Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index f44cba624f..bf4169e723 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Testing.TestingTests .Returns("/hello/world/1234"); var urlProvider = urlProviderMock.Object; - var theUrlProvider = new UrlProvider(umbracoContext, new [] { urlProvider }); + var theUrlProvider = new UrlProvider(umbracoContext, new [] { urlProvider }, umbracoContext.CurrentVariationAccessor); var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.InvariantNeutral); diff --git a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs index 6e8b22378c..240cf2369a 100644 --- a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs @@ -73,7 +73,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var ctrl = new MatchesDefaultIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); @@ -97,7 +97,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var ctrl = new MatchesOverriddenIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); @@ -121,7 +121,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var ctrl = new MatchesCustomIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); @@ -145,7 +145,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var ctrl = new MatchesAsyncIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index e467889831..7ca258affc 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var ctrl = new TestSurfaceController { UmbracoContext = umbracoContext }; @@ -68,7 +68,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var ctrl = new TestSurfaceController { UmbracoContext = umbCtx }; @@ -88,7 +88,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var controller = new TestSurfaceController { UmbracoContext = umbracoContext }; @@ -115,7 +115,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == "AutoLegacy")), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var helper = new UmbracoHelper( @@ -153,7 +153,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(section => section.WebRouting == webRoutingSettings), Enumerable.Empty(), globalSettings, - Mock.Of(), + new TestCurrentVariationAccessor(), true); var content = Mock.Of(publishedContent => publishedContent.Id == 12345); diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index a71612823e..fba1e6b4f6 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -441,7 +441,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, - Mock.Of()); + new TestCurrentVariationAccessor()); //if (setSingleton) //{ diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index 27a4541733..571f74089d 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -82,7 +82,7 @@ namespace Umbraco.Tests.Web var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); - var contentType = new PublishedContentType(666, "alia", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.InvariantNeutral); + var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.InvariantNeutral); var publishedContent = Mock.Of(); Mock.Get(publishedContent).Setup(x => x.Id).Returns(1234); Mock.Get(publishedContent).Setup(x => x.ContentType).Returns(contentType); @@ -104,7 +104,7 @@ namespace Umbraco.Tests.Web //pass in the custom url provider new[]{ testUrlProvider.Object }, globalSettings, - entityService.Object, + new TestCurrentVariationAccessor(), true)) { var output = TemplateUtilities.ParseInternalLinks(input, umbCtx.UrlProvider); diff --git a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs index aa1fce8c85..2cc5861156 100644 --- a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs +++ b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Web TestObjects.GetUmbracoSettings(), new List(), TestObjects.GetGlobalSettings(), - Mock.Of()); + new TestCurrentVariationAccessor()); var r1 = new RouteData(); r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Web TestObjects.GetUmbracoSettings(), new List(), TestObjects.GetGlobalSettings(), - Mock.Of()); + new TestCurrentVariationAccessor()); var r1 = new RouteData(); r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); @@ -78,7 +78,7 @@ namespace Umbraco.Tests.Web TestObjects.GetUmbracoSettings(), new List(), TestObjects.GetGlobalSettings(), - Mock.Of()); + new TestCurrentVariationAccessor()); var httpContext = Mock.Of(); diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 07dcebd763..5e3d2658f7 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -6,7 +6,6 @@ using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Services; using System.Linq; using System.Reflection; @@ -15,12 +14,13 @@ using System.Web.Hosting; using Umbraco.Core.Components; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services.Changes; using Umbraco.Core.Services.Implement; using Umbraco.Web.Composing; using Umbraco.Web.Security; using Umbraco.Web.Services; -using Content = Umbraco.Core.Models.Content; +using LightInject; using ApplicationTree = Umbraco.Core.Models.ApplicationTree; namespace Umbraco.Web.Cache @@ -237,7 +237,7 @@ namespace Umbraco.Web.Cache UmbracoConfig.For.UmbracoSettings(), Current.UrlProviders, UmbracoConfig.For.GlobalSettings(), - Current.Services.EntityService, + Current.Container.GetInstance(), true); } diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 1c91b41bff..c5a0e5ac0b 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.Models [DebuggerDisplay("Content Id: {Id}, Name: {Name}")] public abstract class PublishedContentBase : IPublishedContent { - private string _url; // fixme meaning? + private string _url; // fixme - cannot cache urls! depends on the current request! #region ContentType @@ -84,7 +84,7 @@ namespace Umbraco.Web.Models switch (ItemType) { case PublishedItemType.Content: - // fixme inject an umbraco context accessor! + // fixme - consider injecting an umbraco context accessor if (UmbracoContext.Current == null) throw new InvalidOperationException("Cannot compute Url for a content item when UmbracoContext.Current is null."); if (UmbracoContext.Current.UrlProvider == null) @@ -103,7 +103,8 @@ namespace Umbraco.Web.Models var propType = ContentType.GetPropertyType(Constants.Conventions.Media.File); - // fixme this is horrible we need url providers for media too + this does NOT support variations + // fixme - consider implementing media url providers + // note: that one does not support variations //This is a hack - since we now have 2 properties that support a URL: upload and cropper, we need to detect this since we always // want to return the normal URL and the cropper stores data as json switch (propType.EditorAlias) @@ -130,7 +131,7 @@ namespace Umbraco.Web.Models throw new NotSupportedException(); } } - + /// public abstract PublishedCultureInfos GetCulture(string culture = "."); @@ -166,7 +167,7 @@ namespace Umbraco.Web.Models /// public virtual IPublishedProperty GetProperty(string alias, bool recurse) { - // fixme - but can recurse work with variants? + // fixme - refactor with fallback var property = GetProperty(alias); if (recurse == false) return property; diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index c6d39aa0b0..3b4c976d70 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Data; -using System.Globalization; using System.Linq; using System.Web; using Examine; @@ -123,28 +122,6 @@ namespace Umbraco.Web #region Value - // fixme missing variations, but recurse/variations/fallback = ? - - /// - /// Recursively gets the value of a content's property identified by its alias. - /// - /// The content. - /// The property alias. - /// A value indicating whether to recurse. - /// The recursive value of the content's property identified by the alias. - /// - /// Recursively means: walking up the tree from , get the first value that can be found. - /// The value comes from IPublishedProperty field Value ie it is suitable for use when rendering content. - /// If no property with the specified alias exists, or if the property has no value, returns null. - /// If eg a numeric property wants to default to 0 when value source is empty, this has to be done in the converter. - /// The alias is case-insensitive. - /// - public static object Value(this IPublishedContent content, string alias, bool recurse) - { - var property = content.GetProperty(alias, recurse); - return property?.GetValue(); - } - /// /// Recursively the value of a content's property identified by its alias, if it exists, otherwise a default value. /// @@ -164,7 +141,7 @@ namespace Umbraco.Web /// public static object Value(this IPublishedContent content, string alias, string culture = ".", string segment = ".", object defaultValue = default, bool recurse = false) { - // fixme - variations+recurse not implemented here + // fixme - refactor with fallback var property = content.GetProperty(alias, recurse); return property == null || property.HasValue(culture, segment) == false ? defaultValue : property.GetValue(); } @@ -193,7 +170,7 @@ namespace Umbraco.Web /// public static T Value(this IPublishedContent content, string alias, string culture = ".", string segment = ".", T defaultValue = default, bool recurse = false) { - // fixme - variations+recurse not implemented here + // fixme - refactor with fallback var property = content.GetProperty(alias, recurse); if (property == null) return defaultValue; @@ -209,8 +186,8 @@ namespace Umbraco.Web //TODO: we should pass in the IExamineManager? var searcher = string.IsNullOrEmpty(indexName) - ? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer) - : Examine.ExamineManager.Instance.GetSearcher(indexName); + ? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer) + : ExamineManager.Instance.GetSearcher(indexName); if (searcher == null) throw new InvalidOperationException("No searcher found for index " + indexName); @@ -235,8 +212,8 @@ namespace Umbraco.Web //TODO: we should pass in the IExamineManager? var searcher = string.IsNullOrEmpty(indexName) - ? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer) - : Examine.ExamineManager.Instance.GetSearcher(indexName); + ? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer) + : ExamineManager.Instance.GetSearcher(indexName); if (searcher == null) throw new InvalidOperationException("No searcher found for index " + indexName); @@ -255,7 +232,7 @@ namespace Umbraco.Web { //TODO: we should pass in the IExamineManager? - var s = searchProvider ?? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer); + var s = searchProvider ?? ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer); var results = s.Search(criteria); return results.ToPublishedSearchResults(UmbracoContext.Current.ContentCache); @@ -1170,8 +1147,8 @@ namespace Umbraco.Web /// internal static Func> GetPropertyAliasesAndNames { - get { return _getPropertyAliasesAndNames ?? GetAliasesAndNames; } - set { _getPropertyAliasesAndNames = value; } + get => _getPropertyAliasesAndNames ?? GetAliasesAndNames; + set => _getPropertyAliasesAndNames = value; } private static Dictionary GetAliasesAndNames(ServiceContext services, string alias) diff --git a/src/Umbraco.Web/PublishedElementExtensions.cs b/src/Umbraco.Web/PublishedElementExtensions.cs index 57e71573b5..a7776bb374 100644 --- a/src/Umbraco.Web/PublishedElementExtensions.cs +++ b/src/Umbraco.Web/PublishedElementExtensions.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; -using System.Reflection; using System.Web; using Umbraco.Core.Models.PublishedContent; @@ -56,7 +54,9 @@ namespace Umbraco.Web return prop != null && prop.HasValue(culture, segment); } - // fixme - that one is missing variations + // fixme - .Value() refactoring - in progress + // missing variations... + /// /// Returns one of two strings depending on whether the content has a value for a property identified by its alias. /// @@ -134,7 +134,7 @@ namespace Umbraco.Web #region Value or Umbraco.Field - WORK IN PROGRESS - // fixme - more work-in-progress for element.Value() and element.Value() here + // fixme - .Value() refactoring - in progress // trying to reproduce Umbraco.Field so we can get rid of it // // what we want: @@ -150,10 +150,10 @@ namespace Umbraco.Web // see UmbracoComponentRenderer.Field - which is ugly ;-( // recurse first, on each alias (that's how it's done in Field) - // TODO: strongly typed properties howto? + // // there is no strongly typed recurse, etc => needs to be in ModelsBuilder? - // todo - that one can only happen in ModelsBuilder as that's where the attributes are defined + // that one can only happen in ModelsBuilder as that's where the attributes are defined // the attribute that carries the alias is in ModelsBuilder! //public static TValue Value(this TModel content, Expression> propertySelector, ...) // where TModel : IPublishedElement @@ -164,6 +164,8 @@ namespace Umbraco.Web // return content.Value(alias, ...) //} + // recurse should be implemented via fallback + // todo - that one should be refactored, missing culture and so many things public static IHtmlString Value(this IPublishedElement content, string aliases, Func format, string alt = "") { diff --git a/src/Umbraco.Web/Routing/UrlProvider.cs b/src/Umbraco.Web/Routing/UrlProvider.cs index b8c28814b5..b88245b917 100644 --- a/src/Umbraco.Web/Routing/UrlProvider.cs +++ b/src/Umbraco.Web/Routing/UrlProvider.cs @@ -20,15 +20,16 @@ namespace Umbraco.Web.Routing /// Initializes a new instance of the class with an Umbraco context and a list of url providers. /// /// The Umbraco context. - /// + /// Routing settings. /// The list of url providers. - public UrlProvider(UmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable urlProviders, IEntityService entityService) + /// The current variation accessor. + public UrlProvider(UmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable urlProviders, ICurrentVariationAccessor variationAccessor) { if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings)); _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); - _urlProviders = urlProviders; - _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); + _urlProviders = urlProviders; + _variationAccessor = variationAccessor ?? throw new ArgumentNullException(nameof(variationAccessor)); var provider = UrlProviderMode.Auto; Mode = provider; @@ -43,19 +44,20 @@ namespace Umbraco.Web.Routing /// /// The Umbraco context. /// The list of url providers. - /// - public UrlProvider(UmbracoContext umbracoContext, IEnumerable urlProviders, UrlProviderMode provider = UrlProviderMode.Auto) + /// The current variation accessor. + /// An optional provider mode. + public UrlProvider(UmbracoContext umbracoContext, IEnumerable urlProviders, ICurrentVariationAccessor variationAccessor, UrlProviderMode mode = UrlProviderMode.Auto) { _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _urlProviders = urlProviders; + _variationAccessor = variationAccessor; - Mode = provider; + Mode = mode; } private readonly UmbracoContext _umbracoContext; private readonly IEnumerable _urlProviders; - private readonly IEntityService _entityService; - private readonly ICurrentVariationAccessor _variationAccessor; // fixme set! + private readonly ICurrentVariationAccessor _variationAccessor; /// /// Gets or sets the provider url mode. diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index bd5acab5de..d8602422d5 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -218,6 +218,7 @@ namespace Umbraco.Web.Runtime IUmbracoSettingsSection umbracoSettings, IGlobalSettings globalSettings, IEntityService entityService, + ICurrentVariationAccessor variationAccessor, UrlProviderCollection urlProviders) { // setup mvc and webapi services @@ -255,7 +256,7 @@ namespace Umbraco.Web.Runtime umbracoSettings, urlProviders, globalSettings, - entityService); + variationAccessor); // ensure WebAPI is initialized, after everything GlobalConfiguration.Configuration.EnsureInitialized(); diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index b86c8c29a6..53fab2e57a 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -4,6 +4,7 @@ using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -67,9 +68,9 @@ namespace Umbraco.Web IPublishedSnapshotService publishedSnapshotService, WebSecurity webSecurity, IUmbracoSettingsSection umbracoSettings, - IEnumerable urlProviders, - IGlobalSettings globalSettings, - IEntityService entityService, + IEnumerable urlProviders, + IGlobalSettings globalSettings, + ICurrentVariationAccessor variationAccessor, bool replace = false) { if (umbracoContextAccessor == null) throw new ArgumentNullException(nameof(umbracoContextAccessor)); @@ -87,7 +88,7 @@ namespace Umbraco.Web // create & assign to accessor, dispose existing if any umbracoContextAccessor.UmbracoContext?.Dispose(); - return umbracoContextAccessor.UmbracoContext = new UmbracoContext(httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, entityService); + return umbracoContextAccessor.UmbracoContext = new UmbracoContext(httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, variationAccessor); } // initializes a new instance of the UmbracoContext class @@ -100,13 +101,14 @@ namespace Umbraco.Web IUmbracoSettingsSection umbracoSettings, IEnumerable urlProviders, IGlobalSettings globalSettings, - IEntityService entityService) + ICurrentVariationAccessor variationAccessor) { if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService)); if (webSecurity == null) throw new ArgumentNullException(nameof(webSecurity)); if (umbracoSettings == null) throw new ArgumentNullException(nameof(umbracoSettings)); if (urlProviders == null) throw new ArgumentNullException(nameof(urlProviders)); + CurrentVariationAccessor = variationAccessor ?? throw new ArgumentNullException(nameof(variationAccessor)); _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); // ensure that this instance is disposed when the request terminates, though we *also* ensure @@ -136,7 +138,7 @@ namespace Umbraco.Web // OriginalRequestUrl = GetRequestFromContext()?.Url ?? new Uri("http://localhost"); CleanedUmbracoUrl = UriUtility.UriToUmbraco(OriginalRequestUrl); - UrlProvider = new UrlProvider(this, umbracoSettings.WebRouting, urlProviders, entityService); + UrlProvider = new UrlProvider(this, umbracoSettings.WebRouting, urlProviders, variationAccessor); } #endregion @@ -213,6 +215,8 @@ namespace Umbraco.Web /// public HttpContextBase HttpContext { get; } + public ICurrentVariationAccessor CurrentVariationAccessor { get; } + /// /// Creates and caches an instance of a DomainHelper /// diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 1578f5dc53..5a866939a8 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -1,10 +1,8 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Text; -using System.Threading; using System.Web; using System.Web.Routing; using LightInject; @@ -17,12 +15,12 @@ using Umbraco.Web.Security; using Umbraco.Core.Collections; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Exceptions; +using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; -using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; namespace Umbraco.Web { @@ -55,9 +53,6 @@ namespace Umbraco.Web [Inject] public IUserService UserService { get; set; } - [Inject] - public IEntityService EntityService { get; set; } - [Inject] public UrlProviderCollection UrlProviders { get; set; } @@ -71,7 +66,10 @@ namespace Umbraco.Web internal PublishedRouter PublishedRouter { get; set; } [Inject] - internal IUmbracoDatabaseFactory DatabaseFactory { get; set; } + internal IUmbracoDatabaseFactory DatabaseFactory { get; set; } + + [Inject] + internal ICurrentVariationAccessor CurrentVariationAccessor { get; set; } #endregion @@ -114,8 +112,8 @@ namespace Umbraco.Web new WebSecurity(httpContext, UserService, GlobalSettings), UmbracoConfig.For.UmbracoSettings(), UrlProviders, - GlobalSettings, - EntityService, + GlobalSettings, + CurrentVariationAccessor, true); } diff --git a/src/Umbraco.Web/umbraco.presentation/item.cs b/src/Umbraco.Web/umbraco.presentation/item.cs index 80089afde7..3f648d66c4 100644 --- a/src/Umbraco.Web/umbraco.presentation/item.cs +++ b/src/Umbraco.Web/umbraco.presentation/item.cs @@ -75,7 +75,7 @@ namespace umbraco //check for published content and get its value using that if (publishedContent != null && (publishedContent.HasProperty(_fieldName) || recursive)) { - var pval = publishedContent.Value(_fieldName, recursive); + var pval = publishedContent.Value(_fieldName, recurse: recursive); var rval = pval == null ? string.Empty : pval.ToString(); _fieldContent = rval.IsNullOrWhiteSpace() ? _fieldContent : rval; } @@ -95,7 +95,7 @@ namespace umbraco { if (publishedContent != null && (publishedContent.HasProperty(altFieldName) || recursive)) { - var pval = publishedContent.Value(altFieldName, recursive); + var pval = publishedContent.Value(altFieldName, recurse: recursive); var rval = pval == null ? string.Empty : pval.ToString(); _fieldContent = rval.IsNullOrWhiteSpace() ? _fieldContent : rval; }