From d33cc29f98415371d5078b2015816939da0af4b4 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 29 Apr 2014 09:44:15 +0200 Subject: [PATCH 01/19] Reintroduce IPublishedContentProperty --- src/Umbraco.Core/Dynamics/PropertyResult.cs | 9 +++++++ src/Umbraco.Core/Models/IPublishedProperty.cs | 17 +++++++++++-- .../PublishedContent/PublishedPropertyBase.cs | 9 +++++++ .../PublishedContentTestElements.cs | 9 +++++++ .../PublishedContentPropertyExtension.cs | 25 ++++++++++++++++++- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Dynamics/PropertyResult.cs b/src/Umbraco.Core/Dynamics/PropertyResult.cs index 59d3a0f247..4b6f83c1d2 100644 --- a/src/Umbraco.Core/Dynamics/PropertyResult.cs +++ b/src/Umbraco.Core/Dynamics/PropertyResult.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using Umbraco.Core.Models; using System.Web; @@ -43,5 +44,13 @@ namespace Umbraco.Core.Dynamics var value = Value; return value == null ? string.Empty : value.ToString(); } + + // see notes in IPublishedProperty + [Obsolete("Use PropertyTypeAlias.", true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public string Alias { get { return PropertyTypeAlias; } } + [Obsolete] + [EditorBrowsable(EditorBrowsableState.Never)] + public Guid Version { get { return Guid.Empty; } } } } diff --git a/src/Umbraco.Core/Models/IPublishedProperty.cs b/src/Umbraco.Core/Models/IPublishedProperty.cs index f6afa1f05e..6a93bc85ec 100644 --- a/src/Umbraco.Core/Models/IPublishedProperty.cs +++ b/src/Umbraco.Core/Models/IPublishedProperty.cs @@ -1,9 +1,12 @@ +using System; +using System.ComponentModel; + namespace Umbraco.Core.Models { /// /// Represents a property of an IPublishedContent. /// - public interface IPublishedProperty + public interface IPublishedProperty : IPublishedContentProperty { /// /// Gets the alias of the property. @@ -45,7 +48,7 @@ namespace Umbraco.Core.Models /// It can be null, or any type of CLR object. /// It has been fully prepared and processed by the appropriate converter. /// - object Value { get; } + new object Value { get; } /// /// Gets the XPath value of the property. @@ -57,4 +60,14 @@ namespace Umbraco.Core.Models /// object XPathValue { get; } } + + // had to re-introduce that one for backward-compatibility reasons + [Obsolete("Use IPublishedProperty.", false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public interface IPublishedContentProperty + { + string Alias { get; } + object Value { get; } + Guid Version { get; } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs index b841b85212..06c3dfbfa9 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; namespace Umbraco.Core.Models.PublishedContent { @@ -27,5 +28,13 @@ namespace Umbraco.Core.Models.PublishedContent public abstract object DataValue { get; } public abstract object Value { get; } public abstract object XPathValue { get; } + + // see notes in IPublishedProperty + [Obsolete("Use PropertyTypeAlias.", true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public string Alias { get { return PropertyTypeAlias; } } + [Obsolete] + [EditorBrowsable(EditorBrowsableState.Never)] + public Guid Version { get { return Guid.Empty; } } } } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs index be357c4c03..04414f9e99 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; @@ -231,6 +232,14 @@ namespace Umbraco.Tests.PublishedContent public object Value { get; set; } public bool HasValue { get; set; } public object XPathValue { get; set; } + + // see notes in IPublishedProperty + [Obsolete("Use PropertyTypeAlias.", true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public string Alias { get { return PropertyTypeAlias; } } + [Obsolete] + [EditorBrowsable(EditorBrowsableState.Never)] + public Guid Version { get { return Guid.Empty; } } } [PublishedContentModel("ContentType2")] diff --git a/src/Umbraco.Web/PublishedContentPropertyExtension.cs b/src/Umbraco.Web/PublishedContentPropertyExtension.cs index ee4dd83e57..54a77ddd0c 100644 --- a/src/Umbraco.Web/PublishedContentPropertyExtension.cs +++ b/src/Umbraco.Web/PublishedContentPropertyExtension.cs @@ -1,4 +1,5 @@ -using Umbraco.Core; +using System; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.PropertyEditors; @@ -57,5 +58,27 @@ namespace Umbraco.Web } #endregion + + #region IPublishedContentProperty.GetValue + + // see notes in IPublishedProperty + + public static T GetValue(this IPublishedContentProperty property) + { + var property2 = property as IPublishedProperty; + if (property2 == null) // should never happen + throw new ArgumentException("Not an IPublishedProperty.", "property"); + return property2.GetValue(false, default(T)); + } + + public static T GetValue(this IPublishedContentProperty property, T defaultValue) + { + var property2 = property as IPublishedProperty; + if (property2 == null) // should never happen + throw new ArgumentException("Not an IPublishedProperty.", "property"); + return property2.GetValue(true, defaultValue); + } + + #endregion } } From 771e21681392a98da07ea56b1426e6d262175dd8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 30 Apr 2014 11:21:12 +1000 Subject: [PATCH 02/19] U4-2635 Skip past replaced word when checking Avoids infinite loop if search and replacement are equal --- src/Umbraco.Core/StringExtensions.cs | 15 ++++++++------- .../CoreStrings/StringExtensionsTests.cs | 12 ++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index 18a3136c8f..48bc18a398 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -1123,17 +1123,18 @@ namespace Umbraco.Core /// Updated string public static string Replace(this string source, string oldString, string newString, StringComparison stringComparison) { - var index = source.IndexOf(oldString, stringComparison); + // This initialisation ensures the first check starts at index zero of the source. On successive checks for + // a match, the source is skipped to immediately after the last replaced occurrence for efficiency + // and to avoid infinite loops when oldString and newString compare equal. + int index = -1 * newString.Length; - // Determine if we found a match - var matchFound = index >= 0; - - if (matchFound) + // Determine if there are any matches left in source, starting from just after the result of replacing the last match. + while((index = source.IndexOf(oldString, index + newString.Length, stringComparison)) >= 0) { - // Remove the old text + // Remove the old text. source = source.Remove(index, oldString.Length); - // Add the replacemenet text + // Add the replacemenet text. source = source.Insert(index, newString); } diff --git a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs b/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs index 1474bd98f9..89d03baa2d 100644 --- a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs @@ -80,6 +80,18 @@ namespace Umbraco.Tests.CoreStrings Assert.AreEqual(shouldBe, trimmed); } + [TestCase("Hello this is my string", "hello", "replaced", "replaced this is my string", StringComparison.CurrentCultureIgnoreCase)] + [TestCase("Hello this is hello my string", "hello", "replaced", "replaced this is replaced my string", StringComparison.CurrentCultureIgnoreCase)] + [TestCase("Hello this is my string", "nonexistent", "replaced", "Hello this is my string", StringComparison.CurrentCultureIgnoreCase)] + [TestCase("Hellohello this is my string", "hello", "replaced", "replacedreplaced this is my string", StringComparison.CurrentCultureIgnoreCase)] + // Ensure replacing with the same string doesn't cause infinite loop. + [TestCase("Hello this is my string", "hello", "hello", "hello this is my string", StringComparison.CurrentCultureIgnoreCase)] + public void ReplaceWithStringComparison(string input, string oldString, string newString, string shouldBe, StringComparison stringComparison) + { + var replaced = input.Replace(oldString, newString, stringComparison); + Assert.AreEqual(shouldBe, replaced); + } + [TestCase(null, null)] [TestCase("", "")] [TestCase("x", "X")] From c5559d7721a19c68b8e8bd52cfb9d0e43b233311 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 30 Apr 2014 11:27:47 +1000 Subject: [PATCH 03/19] Specifying assembly for membership/user provider Addresses http://issues.umbraco.org/issue/U4-4781 --- src/Umbraco.Web.UI/web.Template.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 4b2dc22836..34a8dca7e1 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -156,8 +156,8 @@ - - + + From e88e809e2911a1481990bba85befa41a97147686 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 30 Apr 2014 17:39:13 +1000 Subject: [PATCH 04/19] Use new YouTube oembed https end-point (old http one redirects) and make sure videos are embedded over https to allow for https Umbraco sites. --- src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config | 3 ++- src/Umbraco.Web.UI/config/EmbeddedMedia.config | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config index 13cc3aa3e7..8e46fd134b 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config @@ -33,10 +33,11 @@ - + 1 xml + https diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.config index 9866d62581..ae25ac80d5 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.config @@ -33,10 +33,11 @@ - + 1 xml + https From cf2217cfe19aaf46eff483998fa398eb5a604202 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 30 Apr 2014 19:41:40 +1000 Subject: [PATCH 05/19] Fixes MySQL upgrades from < 6.0 --- .../Initial/DatabaseSchemaResult.cs | 2 +- .../Migrations/MigrationAttribute.cs | 15 +++- .../Persistence/Migrations/MigrationRunner.cs | 78 +++++++++++-------- .../AssignMissingPrimaryForMySqlKeys.cs | 11 +-- .../AssignMissingPrimaryForMySqlKeys2.cs | 34 ++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Migrations/MigrationRunnerTests.cs | 4 +- 7 files changed, 100 insertions(+), 45 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs index 3fa8cd4ab0..dcf18527e7 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs @@ -65,7 +65,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial return new Version(4, 7, 0); } - return new Version(4, 9, 0); + return new Version(4, 8, 0); } //if the error is for umbracoServer diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationAttribute.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationAttribute.cs index f49bea5ce0..b42b4aa6b8 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationAttribute.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationAttribute.cs @@ -16,8 +16,21 @@ namespace Umbraco.Core.Persistence.Migrations ProductName = product; } + public MigrationAttribute(string minimumCurrentVersion, string targetVersion, int sortOrder, string product) + { + TargetVersion = new Version(targetVersion); + MinimumCurrentVersion = new Version(minimumCurrentVersion); + SortOrder = sortOrder; + ProductName = product; + } + /// - /// Gets or sets the target version of this migration. + /// Gets the minimum current version for which this migration is allowed to execute + /// + public Version MinimumCurrentVersion { get; private set; } + + /// + /// Gets the target version of this migration. /// public Version TargetVersion { get; private set; } diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index 9bc9cd8e9c..5823c70e79 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -13,13 +13,13 @@ namespace Umbraco.Core.Persistence.Migrations /// public class MigrationRunner { - private readonly Version _configuredVersion; + private readonly Version _currentVersion; private readonly Version _targetVersion; private readonly string _productName; - public MigrationRunner(Version configuredVersion, Version targetVersion, string productName) + public MigrationRunner(Version currentVersion, Version targetVersion, string productName) { - _configuredVersion = configuredVersion; + _currentVersion = currentVersion; _targetVersion = targetVersion; _productName = productName; } @@ -46,20 +46,20 @@ namespace Umbraco.Core.Persistence.Migrations { LogHelper.Info("Initializing database migrations"); - var foundMigrations = MigrationResolver.Current.Migrations.ToArray(); + var foundMigrations = MigrationResolver.Current.Migrations.ToArray(); //filter all non-schema migrations var migrations = isUpgrade ? OrderedUpgradeMigrations(foundMigrations).ToList() : OrderedDowngradeMigrations(foundMigrations).ToList(); - + //SD: Why do we want this? - if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _configuredVersion, _targetVersion, true), this)) + if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, true), this)) return false; //Loop through migrations to generate sql var migrationContext = InitializeMigrations(migrations, database, databaseProvider, isUpgrade); - + try { ExecuteMigrations(migrationContext, database); @@ -81,13 +81,13 @@ namespace Umbraco.Core.Persistence.Migrations throw; } - Migrated.RaiseEvent(new MigrationEventArgs(migrations, migrationContext, _configuredVersion, _targetVersion, false), this); + Migrated.RaiseEvent(new MigrationEventArgs(migrations, migrationContext, _currentVersion, _targetVersion, false), this); return true; } - private void ExecuteMigrations(IMigrationContext context, Database database) - { + private void ExecuteMigrations(IMigrationContext context, Database database) + { //Transactional execution of the sql that was generated from the found migrations using (var transaction = database.GetTransaction()) { @@ -108,13 +108,13 @@ namespace Umbraco.Core.Persistence.Migrations transaction.Complete(); } - } + } internal MigrationContext InitializeMigrations(List migrations, Database database, DatabaseProviders databaseProvider, bool isUpgrade = true) - { + { //Loop through migrations to generate sql var context = new MigrationContext(databaseProvider, database); - + foreach (var migration in migrations) { var baseMigration = migration as MigrationBase; @@ -148,35 +148,49 @@ namespace Umbraco.Core.Persistence.Migrations } return context; - } + } + /// + /// Filters and orders migrations based on the migrations listed and the currently configured version and the target installation version + /// + /// + /// internal IEnumerable OrderedUpgradeMigrations(IEnumerable foundMigrations) { var migrations = (from migration in foundMigrations - let migrationAttributes = migration.GetType().GetCustomAttributes(false) - from migrationAttribute in migrationAttributes - where migrationAttribute != null - where - migrationAttribute.TargetVersion > _configuredVersion && - migrationAttribute.TargetVersion <= _targetVersion && - migrationAttribute.ProductName == _productName - orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder ascending - select migration).Distinct(); + let migrationAttributes = migration.GetType().GetCustomAttributes(false) + from migrationAttribute in migrationAttributes + where migrationAttribute != null + where + migrationAttribute.TargetVersion > _currentVersion && + migrationAttribute.TargetVersion <= _targetVersion && + migrationAttribute.ProductName == _productName && + //filter if the migration specifies a minimum current version for which to execute + (migrationAttribute.MinimumCurrentVersion == null || _currentVersion >= migrationAttribute.MinimumCurrentVersion) + orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder ascending + select migration).Distinct(); return migrations; } + /// + /// Filters and orders migrations based on the migrations listed and the currently configured version and the target installation version + /// + /// + /// public IEnumerable OrderedDowngradeMigrations(IEnumerable foundMigrations) { var migrations = (from migration in foundMigrations - let migrationAttributes = migration.GetType().GetCustomAttributes(false) - from migrationAttribute in migrationAttributes - where migrationAttribute != null - where - migrationAttribute.TargetVersion > _configuredVersion && - migrationAttribute.TargetVersion <= _targetVersion && - migrationAttribute.ProductName == _productName - orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder descending - select migration).Distinct(); + let migrationAttributes = migration.GetType().GetCustomAttributes(false) + from migrationAttribute in migrationAttributes + where migrationAttribute != null + where + migrationAttribute.TargetVersion > _currentVersion && + migrationAttribute.TargetVersion <= _targetVersion && + migrationAttribute.ProductName == _productName && + //filter if the migration specifies a minimum current version for which to execute + (migrationAttribute.MinimumCurrentVersion == null || _currentVersion >= migrationAttribute.MinimumCurrentVersion) + orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder descending + select migration).Distinct(); return migrations; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs index a4fae3ae83..7c7bbf54fb 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero { + //see: http://issues.umbraco.org/issue/U4-4430 [Migration("6.2.0", 0, GlobalSettings.UmbracoMigrationName)] public class AssignMissingPrimaryForMySqlKeys : MigrationBase @@ -14,15 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql) { var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); - - //This should be 2 because this table has 2 keys - if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) - { - Create.PrimaryKey("PK_cmsContentType2ContentType") - .OnTable("cmsContentType2ContentType") - .Columns(new[] {"parentContentTypeId", "childContentTypeId"}); - } - + //This should be 2 because this table has 2 keys if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentTypeAllowedContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) { diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs new file mode 100644 index 0000000000..65e440a1da --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys2.cs @@ -0,0 +1,34 @@ +using System.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero +{ + //We have to target this specifically to ensure this DOES NOT execute if upgrading from a version previous to 6.0, + // this is because when the 6.0.0 migrations are executed, this primary key get's created so if this migration is also executed + // we will get exceptions because it is trying to create the PK two times. + [Migration("6.0.0", "6.2.0", 0, GlobalSettings.UmbracoMigrationName)] + public class AssignMissingPrimaryForMySqlKeys2 : MigrationBase + { + public override void Up() + { + if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql) + { + var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsContentType2ContentType") + .OnTable("cmsContentType2ContentType") + .Columns(new[] {"parentContentTypeId", "childContentTypeId"}); + } + } + } + + public override void Down() + { + //don't do anything, these keys should have always existed! + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7169cc09ae..18be6898de 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -228,6 +228,7 @@ + diff --git a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs index dd28e559bb..d7aca12bfa 100644 --- a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Migrations { var runner = new MigrationRunner(new Version(4, 0, 0), new Version(6, 0, 0), "Test"); - var migrations = runner.OrderedUpgradeMigrations(new List {new MultiMigration()}); + var migrations = runner.OrderedUpgradeMigrations(new List { new MultiMigration() }); var ctx = runner.InitializeMigrations( //new List {new DoRunMigration(), new DoNotRunMigration()}, @@ -58,7 +58,7 @@ namespace Umbraco.Tests.Migrations Assert.AreEqual(1, ctx.Expressions.Count()); } - + [Migration("6.0.0", 1, "Test")] [Migration("5.0.0", 1, "Test")] private class MultiMigration : MigrationBase From a8cc8fa68823a6e7e8b949cab3eb4caf840b06df Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 30 Apr 2014 19:58:59 +1000 Subject: [PATCH 06/19] Fixes case sensitivity with MySQL --- src/Umbraco.Core/DatabaseContext.cs | 31 ++++++++++++++++--- .../Initial/DatabaseSchemaCreation.cs | 2 ++ .../Repositories/ContentRepository.cs | 6 ++-- .../Repositories/ContentTypeRepository.cs | 2 +- .../Repositories/MediaRepository.cs | 6 ++-- .../Repositories/MediaTypeRepository.cs | 2 +- .../Repositories/MemberRepository.cs | 4 +-- .../Repositories/MemberTypeRepository.cs | 2 +- .../Repositories/RecycleBinRepository.cs | 6 ++-- .../Repositories/UserRepository.cs | 2 +- 10 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs index 2bc46688f2..d68c56e5db 100644 --- a/src/Umbraco.Core/DatabaseContext.cs +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -456,6 +456,11 @@ namespace Umbraco.Core string message; var database = new UmbracoDatabase(_connectionString, ProviderName); + + // If MySQL, we're going to ensure that database calls are maintaining proper casing as to remove the necessity for checks + // for case insensitive queries. In an ideal situation (which is what we're striving for), all calls would be case sensitive. + + /* var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database); if (supportsCaseInsensitiveQueries == false) { @@ -468,8 +473,9 @@ namespace Umbraco.Core return new Result { Message = message, Success = false, Percentage = "15" }; } + */ - message = GetResultMessageForMySql(supportsCaseInsensitiveQueries); + message = GetResultMessageForMySql(); var schemaResult = ValidateDatabaseSchema(); var installedVersion = schemaResult.DetermineInstalledVersion(); @@ -520,9 +526,9 @@ namespace Umbraco.Core LogHelper.Info("Database upgrade started"); var database = new UmbracoDatabase(_connectionString, ProviderName); - var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database); + //var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database); - var message = GetResultMessageForMySql(supportsCaseInsensitiveQueries); + var message = GetResultMessageForMySql(); var schemaResult = ValidateDatabaseSchema(); var installedVersion = schemaResult.DetermineInstalledVersion(); @@ -549,6 +555,23 @@ namespace Umbraco.Core } } + private string GetResultMessageForMySql() + { + if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider)) + { + return "

 

Congratulations, the database step ran successfully!

" + + "

Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.

" + + "

However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries

" + + "

Make sure to check with your hosting provider if they support case insensitive queries as well.

" + + "

They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:

" + + "
lower_case_table_names=1

" + + "

For more technical information on case sensitivity in MySQL, have a look at " + + "the documentation on the subject

"; + } + return string.Empty; + } + + /* private string GetResultMessageForMySql(bool? supportsCaseInsensitiveQueries) { if (supportsCaseInsensitiveQueries == null) @@ -572,7 +595,7 @@ namespace Umbraco.Core "the documentation on the subject

"; } return string.Empty; - } + }*/ private Attempt CheckReadyForInstall() { diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index ee10f20730..14dcbb4d59 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -176,6 +176,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial .Where(x => x.IsNullOrWhiteSpace() == false).ToList(); //Add valid and invalid foreign key differences to the result object + // We'll need to do invariant contains with case insensitivity because foreign key, primary key, and even index naming w/ MySQL is not standardized + // In theory you could have: FK_ or fk_ ...or really any standard that your development department (or developer) chooses to use. foreach (var unknown in unknownConstraintsInDatabase) { if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown) || indexesInSchema.InvariantContains(unknown)) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index dc5077293f..c4a437dbc4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -148,12 +148,12 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM umbracoRelation WHERE childId = @Id", "DELETE FROM cmsTagRelationship WHERE nodeId = @Id", "DELETE FROM umbracoDomains WHERE domainRootStructureID = @Id", - "DELETE FROM cmsDocument WHERE NodeId = @Id", + "DELETE FROM cmsDocument WHERE nodeId = @Id", "DELETE FROM cmsPropertyData WHERE contentNodeId = @Id", "DELETE FROM cmsPreviewXml WHERE nodeId = @Id", "DELETE FROM cmsContentVersion WHERE ContentId = @Id", - "DELETE FROM cmsContentXml WHERE nodeID = @Id", - "DELETE FROM cmsContent WHERE NodeId = @Id", + "DELETE FROM cmsContentXml WHERE nodeId = @Id", + "DELETE FROM cmsContent WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs index 948e9d1367..1a95761f1a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -153,7 +153,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM cmsPropertyType WHERE contentTypeId = @Id", "DELETE FROM cmsPropertyTypeGroup WHERE contenttypeNodeId = @Id", "DELETE FROM cmsDocumentType WHERE contentTypeNodeId = @Id", - "DELETE FROM cmsContentType WHERE NodeId = @Id", + "DELETE FROM cmsContentType WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 525ddaf835..c18fd504c4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -135,12 +135,12 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM umbracoRelation WHERE parentId = @Id", "DELETE FROM umbracoRelation WHERE childId = @Id", "DELETE FROM cmsTagRelationship WHERE nodeId = @Id", - "DELETE FROM cmsDocument WHERE NodeId = @Id", + "DELETE FROM cmsDocument WHERE nodeId = @Id", "DELETE FROM cmsPropertyData WHERE contentNodeId = @Id", "DELETE FROM cmsPreviewXml WHERE nodeId = @Id", "DELETE FROM cmsContentVersion WHERE ContentId = @Id", - "DELETE FROM cmsContentXml WHERE nodeID = @Id", - "DELETE FROM cmsContent WHERE NodeId = @Id", + "DELETE FROM cmsContentXml WHERE nodeId = @Id", + "DELETE FROM cmsContent WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs index 18ff7e8e4c..95221f37bf 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -134,7 +134,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM cmsContentType2ContentType WHERE childContentTypeId = @Id", "DELETE FROM cmsPropertyType WHERE contentTypeId = @Id", "DELETE FROM cmsPropertyTypeGroup WHERE contenttypeNodeId = @Id", - "DELETE FROM cmsContentType WHERE NodeId = @Id", + "DELETE FROM cmsContentType WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index bcf6fd490e..28c9feadd4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -184,8 +184,8 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM cmsMember2MemberGroup WHERE Member = @Id", "DELETE FROM cmsMember WHERE nodeId = @Id", "DELETE FROM cmsContentVersion WHERE ContentId = @Id", - "DELETE FROM cmsContentXml WHERE nodeID = @Id", - "DELETE FROM cmsContent WHERE NodeId = @Id", + "DELETE FROM cmsContentXml WHERE nodeId = @Id", + "DELETE FROM cmsContent WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs index ea95936d32..198d5bdb57 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -149,7 +149,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM cmsPropertyType WHERE contentTypeId = @Id", "DELETE FROM cmsPropertyTypeGroup WHERE contenttypeNodeId = @Id", "DELETE FROM cmsMemberType WHERE NodeId = @Id", - "DELETE FROM cmsContentType WHERE NodeId = @Id", + "DELETE FROM cmsContentType WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs index 7397203cff..1ecfe62af7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs @@ -86,12 +86,12 @@ namespace Umbraco.Core.Persistence.Repositories FormatDeleteStatement("umbracoRelation", "childId"), FormatDeleteStatement("cmsTagRelationship", "nodeId"), FormatDeleteStatement("umbracoDomains", "domainRootStructureID"), - FormatDeleteStatement("cmsDocument", "NodeId"), + FormatDeleteStatement("cmsDocument", "nodeId"), FormatDeleteStatement("cmsPropertyData", "contentNodeId"), FormatDeleteStatement("cmsPreviewXml", "nodeId"), FormatDeleteStatement("cmsContentVersion", "ContentId"), - FormatDeleteStatement("cmsContentXml", "nodeID"), - FormatDeleteStatement("cmsContent", "NodeId"), + FormatDeleteStatement("cmsContentXml", "nodeId"), + FormatDeleteStatement("cmsContent", "nodeId"), "UPDATE umbracoNode SET parentID = '-20' WHERE trashed = '1' AND nodeObjectType = @NodeObjectType", "DELETE FROM umbracoNode WHERE trashed = '1' AND nodeObjectType = @NodeObjectType" }; diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index fb6ed8ef39..a2b91a8447 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -136,7 +136,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM cmsTask WHERE parentUserId = @Id", "DELETE FROM umbracoUser2NodePermission WHERE userId = @Id", "DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id", - "DELETE FROM umbracoUserLogins WHERE userId = @Id", + "DELETE FROM umbracoUserLogins WHERE userID = @Id", "DELETE FROM umbracoUser2app WHERE " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("user") + "=@Id", "DELETE FROM umbracoUser WHERE id = @Id" }; From 3134668cece24bf613652cce7952da8b54752de1 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 30 Apr 2014 12:00:08 +0200 Subject: [PATCH 07/19] Bump version number --- build/Build.bat | 2 +- build/NuSpecs/build/UmbracoCms.targets | 2 +- src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/Build.bat b/build/Build.bat index 9ad1fd214d..cf9c5ace51 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -1,6 +1,6 @@ @ECHO OFF SET release=6.2.0 -SET comment=RC +SET comment= SET version=%release% IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%) diff --git a/build/NuSpecs/build/UmbracoCms.targets b/build/NuSpecs/build/UmbracoCms.targets index 04a60d1d44..58b66bfb0f 100644 --- a/build/NuSpecs/build/UmbracoCms.targets +++ b/build/NuSpecs/build/UmbracoCms.targets @@ -1,7 +1,7 @@  - 6.2.0-RC + 6.2.0 diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 9823d31f6b..f1b8d39765 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration /// Gets the version comment (like beta or RC). ///
/// The version comment. - public static string CurrentComment { get { return "RC"; } } + public static string CurrentComment { get { return ""; } } // Get the version of the umbraco.dll by looking at a class in that dll // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx From 0501b181ce4aa9d43a0b285842012ea9297bdf2d Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 30 Apr 2014 15:45:48 +0200 Subject: [PATCH 08/19] Refactor template aliases to strict aliases --- src/Umbraco.Core/Models/Template.cs | 5 +++-- src/Umbraco.Core/Strings/CleanStringType.cs | 10 ++++++++-- src/Umbraco.Core/Strings/DefaultShortStringHelper.cs | 6 ++++++ src/umbraco.cms/businesslogic/template/Template.cs | 9 +++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index 2a2f59d132..25347fd861 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -5,6 +5,7 @@ using System.Runtime.Serialization; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Strings; namespace Umbraco.Core.Models { @@ -42,8 +43,8 @@ namespace Umbraco.Core.Models { base.Path = path; ParentId = -1; - _name = name.Replace("/", ".").Replace("\\", ""); - _alias = alias.ToSafeAlias(); + _name = name; //.Replace("/", ".").Replace("\\", ""); // why? that's just the name! + _alias = alias.ToCleanString(CleanStringType.UnderscoreAlias); } [DataMember] diff --git a/src/Umbraco.Core/Strings/CleanStringType.cs b/src/Umbraco.Core/Strings/CleanStringType.cs index ea9603ec6f..0e0a7c9908 100644 --- a/src/Umbraco.Core/Strings/CleanStringType.cs +++ b/src/Umbraco.Core/Strings/CleanStringType.cs @@ -92,7 +92,7 @@ namespace Umbraco.Core.Strings /// /// Flag mask for role. /// - RoleMask = UrlSegment | Alias | FileName | ConvertCase, + RoleMask = UrlSegment | Alias | UnderscoreAlias | FileName | ConvertCase, /// /// Url role. @@ -112,6 +112,12 @@ namespace Umbraco.Core.Strings /// /// ConvertCase role. /// - ConvertCase = 0x080000 + ConvertCase = 0x080000, + + /// + /// UnderscoreAlias role. + /// + /// This is Alias + leading underscore. + UnderscoreAlias = 0x100000 } } diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index 508e356f71..879f4f0115 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -193,6 +193,12 @@ namespace Umbraco.Core.Strings : (char.IsLetterOrDigit(c) || c == '_'), // letter, digit or underscore StringType = CleanStringType.Ascii | CleanStringType.UmbracoCase, BreakTermsOnUpper = false + }).WithConfig(CleanStringType.UnderscoreAlias, new Config + { + PreFilter = ApplyUrlReplaceCharacters, + IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore + StringType = CleanStringType.Ascii | CleanStringType.UmbracoCase, + BreakTermsOnUpper = false }).WithConfig(CleanStringType.ConvertCase, new Config { PreFilter = null, diff --git a/src/umbraco.cms/businesslogic/template/Template.cs b/src/umbraco.cms/businesslogic/template/Template.cs index 38a05adbf2..08f6e5d5e3 100644 --- a/src/umbraco.cms/businesslogic/template/Template.cs +++ b/src/umbraco.cms/businesslogic/template/Template.cs @@ -6,6 +6,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Strings; using umbraco.DataLayer; using System.Text.RegularExpressions; using System.IO; @@ -204,7 +205,7 @@ namespace umbraco.cms.businesslogic.template { FlushCache(); _oldAlias = _alias; - _alias = value; + _alias = value.ToCleanString(CleanStringType.UnderscoreAlias); SqlHelper.ExecuteNonQuery("Update cmsTemplate set alias = @alias where NodeId = " + this.Id, SqlHelper.CreateParameter("@alias", _alias)); _templateAliasesInitialized = false; @@ -402,13 +403,13 @@ namespace umbraco.cms.businesslogic.template var node = MakeNew(-1, ObjectType, u.Id, 1, name, Guid.NewGuid()); //ensure unique alias - name = helpers.Casing.SafeAlias(name); + name = name.ToCleanString(CleanStringType.UnderscoreAlias); if (GetByAlias(name) != null) name = EnsureUniqueAlias(name, 1); - name = name.Replace("/", ".").Replace("\\", ""); + //name = name.Replace("/", ".").Replace("\\", ""); //why? ToSafeAlias() already removes those chars if (name.Length > 100) - name = name.Substring(0, 95) + "..."; + name = name.Substring(0, 95); // + "..."; // no, these are invalid alias chars SqlHelper.ExecuteNonQuery("INSERT INTO cmsTemplate (NodeId, Alias, design, master) VALUES (@nodeId, @alias, @design, @master)", From 7d8da56dcb75190d6b5330b933a9002754252672 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 30 Apr 2014 16:32:42 +0200 Subject: [PATCH 09/19] Revert "Reintroduce IPublishedContentProperty" This reverts commit d33cc29f98415371d5078b2015816939da0af4b4. --- src/Umbraco.Core/Dynamics/PropertyResult.cs | 9 ------- src/Umbraco.Core/Models/IPublishedProperty.cs | 17 ++----------- .../PublishedContent/PublishedPropertyBase.cs | 9 ------- .../PublishedContentTestElements.cs | 9 ------- .../PublishedContentPropertyExtension.cs | 25 +------------------ 5 files changed, 3 insertions(+), 66 deletions(-) diff --git a/src/Umbraco.Core/Dynamics/PropertyResult.cs b/src/Umbraco.Core/Dynamics/PropertyResult.cs index 4b6f83c1d2..59d3a0f247 100644 --- a/src/Umbraco.Core/Dynamics/PropertyResult.cs +++ b/src/Umbraco.Core/Dynamics/PropertyResult.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel; using Umbraco.Core.Models; using System.Web; @@ -44,13 +43,5 @@ namespace Umbraco.Core.Dynamics var value = Value; return value == null ? string.Empty : value.ToString(); } - - // see notes in IPublishedProperty - [Obsolete("Use PropertyTypeAlias.", true)] - [EditorBrowsable(EditorBrowsableState.Never)] - public string Alias { get { return PropertyTypeAlias; } } - [Obsolete] - [EditorBrowsable(EditorBrowsableState.Never)] - public Guid Version { get { return Guid.Empty; } } } } diff --git a/src/Umbraco.Core/Models/IPublishedProperty.cs b/src/Umbraco.Core/Models/IPublishedProperty.cs index 6a93bc85ec..f6afa1f05e 100644 --- a/src/Umbraco.Core/Models/IPublishedProperty.cs +++ b/src/Umbraco.Core/Models/IPublishedProperty.cs @@ -1,12 +1,9 @@ -using System; -using System.ComponentModel; - namespace Umbraco.Core.Models { /// /// Represents a property of an IPublishedContent. /// - public interface IPublishedProperty : IPublishedContentProperty + public interface IPublishedProperty { /// /// Gets the alias of the property. @@ -48,7 +45,7 @@ namespace Umbraco.Core.Models /// It can be null, or any type of CLR object. /// It has been fully prepared and processed by the appropriate converter. /// - new object Value { get; } + object Value { get; } /// /// Gets the XPath value of the property. @@ -60,14 +57,4 @@ namespace Umbraco.Core.Models /// object XPathValue { get; } } - - // had to re-introduce that one for backward-compatibility reasons - [Obsolete("Use IPublishedProperty.", false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public interface IPublishedContentProperty - { - string Alias { get; } - object Value { get; } - Guid Version { get; } - } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs index 06c3dfbfa9..b841b85212 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel; namespace Umbraco.Core.Models.PublishedContent { @@ -28,13 +27,5 @@ namespace Umbraco.Core.Models.PublishedContent public abstract object DataValue { get; } public abstract object Value { get; } public abstract object XPathValue { get; } - - // see notes in IPublishedProperty - [Obsolete("Use PropertyTypeAlias.", true)] - [EditorBrowsable(EditorBrowsableState.Never)] - public string Alias { get { return PropertyTypeAlias; } } - [Obsolete] - [EditorBrowsable(EditorBrowsableState.Never)] - public Guid Version { get { return Guid.Empty; } } } } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs index 04414f9e99..be357c4c03 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; @@ -232,14 +231,6 @@ namespace Umbraco.Tests.PublishedContent public object Value { get; set; } public bool HasValue { get; set; } public object XPathValue { get; set; } - - // see notes in IPublishedProperty - [Obsolete("Use PropertyTypeAlias.", true)] - [EditorBrowsable(EditorBrowsableState.Never)] - public string Alias { get { return PropertyTypeAlias; } } - [Obsolete] - [EditorBrowsable(EditorBrowsableState.Never)] - public Guid Version { get { return Guid.Empty; } } } [PublishedContentModel("ContentType2")] diff --git a/src/Umbraco.Web/PublishedContentPropertyExtension.cs b/src/Umbraco.Web/PublishedContentPropertyExtension.cs index 54a77ddd0c..ee4dd83e57 100644 --- a/src/Umbraco.Web/PublishedContentPropertyExtension.cs +++ b/src/Umbraco.Web/PublishedContentPropertyExtension.cs @@ -1,5 +1,4 @@ -using System; -using Umbraco.Core; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.PropertyEditors; @@ -58,27 +57,5 @@ namespace Umbraco.Web } #endregion - - #region IPublishedContentProperty.GetValue - - // see notes in IPublishedProperty - - public static T GetValue(this IPublishedContentProperty property) - { - var property2 = property as IPublishedProperty; - if (property2 == null) // should never happen - throw new ArgumentException("Not an IPublishedProperty.", "property"); - return property2.GetValue(false, default(T)); - } - - public static T GetValue(this IPublishedContentProperty property, T defaultValue) - { - var property2 = property as IPublishedProperty; - if (property2 == null) // should never happen - throw new ArgumentException("Not an IPublishedProperty.", "property"); - return property2.GetValue(true, defaultValue); - } - - #endregion } } From cd5581bef6f21c8b63f9b0d0e66d4c2b4c3e95dc Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 30 Apr 2014 16:35:12 +0200 Subject: [PATCH 10/19] Back to IPublishedContentProperty (for 6 only) --- src/Umbraco.Core/Dynamics/PropertyResult.cs | 6 ++--- src/Umbraco.Core/Models/IPublishedContent.cs | 6 ++--- ...operty.cs => IPublishedContentProperty.cs} | 2 +- .../IPublishedContentExtended.cs | 2 +- .../PublishedContentExtended.cs | 10 ++++----- .../PublishedContentWrapped.cs | 6 ++--- .../PublishedContent/PublishedPropertyBase.cs | 2 +- .../PublishedContent/PublishedPropertyType.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../CodeFirst/ContentTypeBase.cs | 4 ++-- .../PublishedContentDataTableTests.cs | 10 ++++----- .../PublishedContentMoreTests.cs | 6 ++--- .../PublishedContentRequestEngineTests.cs | 2 +- .../PublishedContentTestElements.cs | 8 +++---- .../Models/DynamicPublishedContent.cs | 10 ++++----- .../Models/PublishedContentBase.cs | 6 ++--- src/Umbraco.Web/Models/PublishedProperty.cs | 4 ++-- .../PublishedCache/MemberPublishedContent.cs | 8 +++---- .../XmlPublishedCache/PublishedFragment.cs | 8 +++---- .../XmlPublishedCache/PublishedMediaCache.cs | 22 +++++++++---------- .../XmlPublishedCache/XmlPublishedContent.cs | 12 +++++----- src/Umbraco.Web/PublishedContentExtensions.cs | 2 +- .../PublishedContentPropertyExtension.cs | 6 ++--- .../CompatibilityHelper.cs | 6 ++--- 24 files changed, 76 insertions(+), 76 deletions(-) rename src/Umbraco.Core/Models/{IPublishedProperty.cs => IPublishedContentProperty.cs} (98%) diff --git a/src/Umbraco.Core/Dynamics/PropertyResult.cs b/src/Umbraco.Core/Dynamics/PropertyResult.cs index 59d3a0f247..55182593a2 100644 --- a/src/Umbraco.Core/Dynamics/PropertyResult.cs +++ b/src/Umbraco.Core/Dynamics/PropertyResult.cs @@ -4,14 +4,14 @@ using System.Web; namespace Umbraco.Core.Dynamics { - internal class PropertyResult : IPublishedProperty, IHtmlString + internal class PropertyResult : IPublishedContentProperty, IHtmlString { - private readonly IPublishedProperty _source; + private readonly IPublishedContentProperty _source; private readonly string _alias; private readonly object _value; private readonly PropertyResultType _type; - internal PropertyResult(IPublishedProperty source, PropertyResultType type) + internal PropertyResult(IPublishedContentProperty source, PropertyResultType type) { if (source == null) throw new ArgumentNullException("source"); diff --git a/src/Umbraco.Core/Models/IPublishedContent.cs b/src/Umbraco.Core/Models/IPublishedContent.cs index 854ddfd47d..7eb38c0b12 100644 --- a/src/Umbraco.Core/Models/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/IPublishedContent.cs @@ -107,7 +107,7 @@ namespace Umbraco.Core.Models /// The properties collection of an IPublishedContent instance should be read-only ie it is illegal /// to add properties to the collection. /// - ICollection Properties { get; } + ICollection Properties { get; } /// /// Gets a property identified by its alias. @@ -119,7 +119,7 @@ namespace Umbraco.Core.Models /// otherwise return a property -- that may have no value (ie HasValue is false). /// The alias is case-insensitive. /// - IPublishedProperty GetProperty(string alias); + IPublishedContentProperty GetProperty(string alias); /// /// Gets a property identified by its alias. @@ -133,7 +133,7 @@ namespace Umbraco.Core.Models /// return the first property that was found with the alias but had no value (ie HasValue is false). /// The alias is case-insensitive. /// - IPublishedProperty GetProperty(string alias, bool recurse); + IPublishedContentProperty GetProperty(string alias, bool recurse); /// /// Gets the value of a property identified by its alias. diff --git a/src/Umbraco.Core/Models/IPublishedProperty.cs b/src/Umbraco.Core/Models/IPublishedContentProperty.cs similarity index 98% rename from src/Umbraco.Core/Models/IPublishedProperty.cs rename to src/Umbraco.Core/Models/IPublishedContentProperty.cs index f6afa1f05e..96e9f0c22a 100644 --- a/src/Umbraco.Core/Models/IPublishedProperty.cs +++ b/src/Umbraco.Core/Models/IPublishedContentProperty.cs @@ -3,7 +3,7 @@ namespace Umbraco.Core.Models /// /// Represents a property of an IPublishedContent. /// - public interface IPublishedProperty + public interface IPublishedContentProperty { /// /// Gets the alias of the property. diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentExtended.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentExtended.cs index 1a05c2e07a..573e566eac 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentExtended.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentExtended.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Models.PublishedContent /// Adds a property to the extended content. /// /// The property to add. - void AddProperty(IPublishedProperty property); + void AddProperty(IPublishedContentProperty property); /// /// Gets a value indicating whether properties were added to the extended content. diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtended.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtended.cs index 86ebb83919..00e9af5800 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtended.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtended.cs @@ -66,10 +66,10 @@ namespace Umbraco.Core.Models.PublishedContent #region IPublishedContentExtended - void IPublishedContentExtended.AddProperty(IPublishedProperty property) + void IPublishedContentExtended.AddProperty(IPublishedContentProperty property) { if (_properties == null) - _properties = new Collection(); + _properties = new Collection(); _properties.Add(property); } @@ -113,9 +113,9 @@ namespace Umbraco.Core.Models.PublishedContent #region Properties - private ICollection _properties; + private ICollection _properties; - public override ICollection Properties + public override ICollection Properties { get { @@ -138,7 +138,7 @@ namespace Umbraco.Core.Models.PublishedContent } } - public override IPublishedProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return _properties == null ? Content.GetProperty(alias) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs index 38e2537b40..0d485d9bc4 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs @@ -183,7 +183,7 @@ namespace Umbraco.Core.Models.PublishedContent #region Properties - public virtual ICollection Properties + public virtual ICollection Properties { get { return Content.Properties; } } @@ -193,12 +193,12 @@ namespace Umbraco.Core.Models.PublishedContent get { return Content[alias]; } } - public virtual IPublishedProperty GetProperty(string alias) + public virtual IPublishedContentProperty GetProperty(string alias) { return Content.GetProperty(alias); } - public virtual IPublishedProperty GetProperty(string alias, bool recurse) + public virtual IPublishedContentProperty GetProperty(string alias, bool recurse) { return Content.GetProperty(alias, recurse); } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs index b841b85212..3afc80fe4b 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Models.PublishedContent /// Provides a base class for IPublishedProperty implementations which converts and caches /// the value source to the actual value to use when rendering content. /// - internal abstract class PublishedPropertyBase : IPublishedProperty + internal abstract class PublishedPropertyBase : IPublishedContentProperty { public readonly PublishedPropertyType PropertyType; diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index 1f7c6ef0ce..6decafe35e 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -10,7 +10,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Core.Models.PublishedContent { /// - /// Represents an type. + /// Represents an type. /// /// Instances of the class are immutable, ie /// if the property type changes, then a new class needs to be created. diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 18be6898de..815fe33ac4 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -201,6 +201,7 @@ + @@ -737,7 +738,6 @@ - diff --git a/src/Umbraco.Tests/CodeFirst/ContentTypeBase.cs b/src/Umbraco.Tests/CodeFirst/ContentTypeBase.cs index 2f175ad668..2de26d87f1 100644 --- a/src/Umbraco.Tests/CodeFirst/ContentTypeBase.cs +++ b/src/Umbraco.Tests/CodeFirst/ContentTypeBase.cs @@ -93,7 +93,7 @@ namespace Umbraco.Tests.CodeFirst //Using this attribute to hide Properties from Intellisense (when compiled?) [EditorBrowsable(EditorBrowsableState.Never)] - public ICollection Properties + public ICollection Properties { get { return _content.Properties; } } @@ -107,7 +107,7 @@ namespace Umbraco.Tests.CodeFirst //Using this attribute to hide Properties from Intellisense (when compiled?) [EditorBrowsable(EditorBrowsableState.Never)] - public IPublishedProperty GetProperty(string alias) + public IPublishedContentProperty GetProperty(string alias) { return _content.GetProperty(alias); } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index 59b75b4e03..e10676864a 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -145,8 +145,8 @@ namespace Umbraco.Tests.PublishedContent WriterName = "Shannon", Parent = null, Level = 1, - Properties = new Collection( - new List() + Properties = new Collection( + new List() { new PropertyResult("property1", "value" + indexVals, Guid.NewGuid(), PropertyResultType.UserProperty), new PropertyResult("property2", "value" + (indexVals + 1), Guid.NewGuid(), PropertyResultType.UserProperty) @@ -211,7 +211,7 @@ namespace Umbraco.Tests.PublishedContent public bool IsDraft { get; set; } public int GetIndex() { throw new NotImplementedException();} - public ICollection Properties { get; set; } + public ICollection Properties { get; set; } public object this[string propertyAlias] { @@ -220,12 +220,12 @@ namespace Umbraco.Tests.PublishedContent public IEnumerable Children { get; set; } - public IPublishedProperty GetProperty(string alias) + public IPublishedContentProperty GetProperty(string alias) { return Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); } - public IPublishedProperty GetProperty(string alias, bool recurse) + public IPublishedContentProperty GetProperty(string alias, bool recurse) { var property = GetProperty(alias); if (recurse == false) return property; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 6d5c9065d7..d103bee6cc 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -226,7 +226,7 @@ namespace Umbraco.Tests.PublishedContent Url = "/content-1", ParentId = -1, ChildIds = new int[] {}, - Properties = new Collection + Properties = new Collection { new SolidPublishedProperty { @@ -249,7 +249,7 @@ namespace Umbraco.Tests.PublishedContent Url = "/content-2", ParentId = -1, ChildIds = new int[] { }, - Properties = new Collection + Properties = new Collection { new SolidPublishedProperty { @@ -272,7 +272,7 @@ namespace Umbraco.Tests.PublishedContent Url = "/content-2sub", ParentId = -1, ChildIds = new int[] { }, - Properties = new Collection + Properties = new Collection { new SolidPublishedProperty { diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentRequestEngineTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentRequestEngineTests.cs index 25fa7df5f7..b7c2bce299 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentRequestEngineTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentRequestEngineTests.cs @@ -96,7 +96,7 @@ namespace Umbraco.Tests.PublishedContent pc.Setup(content => content.Version).Returns(Guid.NewGuid); pc.Setup(content => content.Parent).Returns(() => null); pc.Setup(content => content.Version).Returns(Guid.NewGuid); - pc.Setup(content => content.Properties).Returns(new Collection()); + pc.Setup(content => content.Properties).Returns(new Collection()); return pc; } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs index be357c4c03..d37dd8a15d 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs @@ -185,14 +185,14 @@ namespace Umbraco.Tests.PublishedContent #region Properties - public ICollection Properties { get; set; } + public ICollection Properties { get; set; } - public IPublishedProperty GetProperty(string alias) + public IPublishedContentProperty GetProperty(string alias) { return Properties.FirstOrDefault(p => p.PropertyTypeAlias.InvariantEquals(alias)); } - public IPublishedProperty GetProperty(string alias, bool recurse) + public IPublishedContentProperty GetProperty(string alias, bool recurse) { var property = GetProperty(alias); if (recurse == false) return property; @@ -219,7 +219,7 @@ namespace Umbraco.Tests.PublishedContent #endregion } - class SolidPublishedProperty : IPublishedProperty + class SolidPublishedProperty : IPublishedContentProperty { public SolidPublishedProperty() { diff --git a/src/Umbraco.Web/Models/DynamicPublishedContent.cs b/src/Umbraco.Web/Models/DynamicPublishedContent.cs index eb476f50a0..209fc7f3bb 100644 --- a/src/Umbraco.Web/Models/DynamicPublishedContent.cs +++ b/src/Umbraco.Web/Models/DynamicPublishedContent.cs @@ -435,7 +435,7 @@ namespace Umbraco.Web.Models return PublishedContent.GetIndex(); } - ICollection IPublishedContent.Properties + ICollection IPublishedContent.Properties { get { return PublishedContent.Properties; } } @@ -445,7 +445,7 @@ namespace Umbraco.Web.Models get { return PublishedContent.Children; } } - IPublishedProperty IPublishedContent.GetProperty(string alias) + IPublishedContentProperty IPublishedContent.GetProperty(string alias) { return PublishedContent.GetProperty(alias); } @@ -545,7 +545,7 @@ namespace Umbraco.Web.Models // get { return PublishedContent.Published; } //} - public IEnumerable Properties + public IEnumerable Properties { get { return PublishedContent.Properties; } } @@ -562,14 +562,14 @@ namespace Umbraco.Web.Models // enhanced versions of the extension methods that exist for IPublishedContent, // here we support the recursive (_) and reflected (@) syntax - public IPublishedProperty GetProperty(string alias) + public IPublishedContentProperty GetProperty(string alias) { return alias.StartsWith("_") ? GetProperty(alias.Substring(1), true) : GetProperty(alias, false); } - public IPublishedProperty GetProperty(string alias, bool recurse) + public IPublishedContentProperty GetProperty(string alias, bool recurse) { if (alias.StartsWith("@")) return GetReflectedProperty(alias.Substring(1)); diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 2ca1978c29..e59c2981cb 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -123,7 +123,7 @@ namespace Umbraco.Web.Models /// /// Gets the properties of the content. /// - public abstract ICollection Properties { get; } + public abstract ICollection Properties { get; } /// /// Gets the value of a property identified by its alias. @@ -158,7 +158,7 @@ namespace Umbraco.Web.Models /// The returned property may have no value (ie HasValue is false). /// The alias is case-insensitive. /// - public abstract IPublishedProperty GetProperty(string alias); + public abstract IPublishedContentProperty GetProperty(string alias); /// /// Gets a property identified by its alias. @@ -172,7 +172,7 @@ namespace Umbraco.Web.Models /// return the first property that was found with the alias but had no value (ie HasValue is false). /// The alias is case-insensitive. /// - public virtual IPublishedProperty GetProperty(string alias, bool recurse) + public virtual IPublishedContentProperty GetProperty(string alias, bool recurse) { var property = GetProperty(alias); if (recurse == false) return property; diff --git a/src/Umbraco.Web/Models/PublishedProperty.cs b/src/Umbraco.Web/Models/PublishedProperty.cs index 0865f8f915..3296ace8ca 100644 --- a/src/Umbraco.Web/Models/PublishedProperty.cs +++ b/src/Umbraco.Web/Models/PublishedProperty.cs @@ -24,9 +24,9 @@ namespace Umbraco.Web.Models /// A collection of IPublishedProperty corresponding to the collection of PublishedPropertyType /// and taking values from the collection of Property. /// Ensures that all conversions took place correctly. - internal static IEnumerable MapProperties( + internal static IEnumerable MapProperties( IEnumerable propertyTypes, IEnumerable properties, - Func map) + Func map) { return propertyTypes.Select(x => { diff --git a/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs b/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs index bdbc28f3cf..4e5d0efa39 100644 --- a/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.PublishedCache private readonly IMember _member; private readonly MembershipUser _membershipUser; - private readonly IPublishedProperty[] _properties; + private readonly IPublishedContentProperty[] _properties; private readonly PublishedContentType _publishedMemberType; public MemberPublishedContent(IMember member, MembershipUser membershipUser) @@ -106,12 +106,12 @@ namespace Umbraco.Web.PublishedCache get { return Enumerable.Empty(); } } - public override ICollection Properties + public override ICollection Properties { get { return _properties; } } - public override IPublishedProperty GetProperty(string alias, bool recurse) + public override IPublishedContentProperty GetProperty(string alias, bool recurse) { if (recurse) { @@ -120,7 +120,7 @@ namespace Umbraco.Web.PublishedCache return GetProperty(alias); } - public override IPublishedProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return _properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs index 860f9f043f..01093e01c5 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedFragment.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache class PublishedFragment : PublishedContentBase { private readonly PublishedContentType _contentType; - private readonly IPublishedProperty[] _properties; + private readonly IPublishedContentProperty[] _properties; public PublishedFragment(string contentTypeAlias, IDictionary dataValues, bool isPreviewing, bool managed) @@ -35,7 +35,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache ? new PublishedFragmentProperty(x, this, dataValue) : new PublishedFragmentProperty(x, this); }) - .Cast() + .Cast() .ToArray(); } @@ -142,12 +142,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache get { throw new NotImplementedException(); } } - public override ICollection Properties + public override ICollection Properties { get { return _properties; } } - public override IPublishedProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return _properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 9217a8ac87..0db5014f98 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -317,7 +317,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// /// - private IPublishedProperty GetProperty(DictionaryPublishedContent dd, string alias) + private IPublishedContentProperty GetProperty(DictionaryPublishedContent dd, string alias) { if (dd.LoadedFromExamine) { @@ -485,7 +485,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IDictionary valueDictionary, Func getParent, Func> getChildren, - Func getProperty, + Func getProperty, bool fromExamine) { if (valueDictionary == null) throw new ArgumentNullException("valueDictionary"); @@ -524,12 +524,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache }, "parentID"); _contentType = PublishedContentType.Get(PublishedItemType.Media, _documentTypeAlias); - _properties = new Collection(); + _properties = new Collection(); //loop through remaining values that haven't been applied foreach (var i in valueDictionary.Where(x => !_keysAdded.Contains(x.Key))) { - IPublishedProperty property; + IPublishedContentProperty property; // must ignore that one if (i.Key == "version" || i.Key == "isDoc") continue; @@ -595,7 +595,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly Func _getParent; private readonly Func> _getChildren; - private readonly Func _getProperty; + private readonly Func _getProperty; /// /// Returns 'Media' as the item type @@ -700,7 +700,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache get { return false; } } - public override ICollection Properties + public override ICollection Properties { get { return _properties; } } @@ -710,7 +710,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache get { return _getChildren(this); } } - public override IPublishedProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return _getProperty(this, alias); } @@ -723,11 +723,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // override to implement cache // cache at context level, ie once for the whole request // but cache is not shared by requests because we wouldn't know how to clear it - public override IPublishedProperty GetProperty(string alias, bool recurse) + public override IPublishedContentProperty GetProperty(string alias, bool recurse) { if (recurse == false) return GetProperty(alias); - IPublishedProperty property; + IPublishedContentProperty property; string key = null; var cache = UmbracoContextCache.Current; @@ -737,7 +737,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache object o; if (cache.TryGetValue(key, out o)) { - property = o as IPublishedProperty; + property = o as IPublishedContentProperty; if (property == null) throw new InvalidOperationException("Corrupted cache."); return property; @@ -770,7 +770,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private DateTime _updateDate; private Guid _version; private int _level; - private readonly ICollection _properties; + private readonly ICollection _properties; private readonly PublishedContentType _contentType; private void ValidateAndSetProperty(IDictionary valueDictionary, Action setProperty, params string[] potentialKeys) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index 5bcca93da5..cc10f9a64f 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -77,7 +77,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private DateTime _createDate; private DateTime _updateDate; private Guid _version; - private IPublishedProperty[] _properties; + private IPublishedContentProperty[] _properties; private int _sortOrder; private int _level; private bool _isDraft; @@ -96,7 +96,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache } } - public override IPublishedProperty GetProperty(string alias) + public override IPublishedContentProperty GetProperty(string alias) { return Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); } @@ -104,7 +104,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // override to implement cache // cache at context level, ie once for the whole request // but cache is not shared by requests because we wouldn't know how to clear it - public override IPublishedProperty GetProperty(string alias, bool recurse) + public override IPublishedContentProperty GetProperty(string alias, bool recurse) { if (recurse == false) return GetProperty(alias); @@ -118,7 +118,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache if (value == null) return null; - var property = value as IPublishedProperty; + var property = value as IPublishedContentProperty; if (property == null) throw new InvalidOperationException("Corrupted cache."); @@ -310,7 +310,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache } } - public override ICollection Properties + public override ICollection Properties { get { @@ -422,7 +422,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache return propertyNodes.TryGetValue(p.PropertyTypeAlias.ToLowerInvariant(), out n) ? new XmlPublishedProperty(p, _isPreviewing, n) : new XmlPublishedProperty(p, _isPreviewing); - }).Cast().ToArray(); + }).Cast().ToArray(); // warn: this is not thread-safe... _initialized = true; diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 411d1a9e7b..09036c14c6 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1702,7 +1702,7 @@ namespace Umbraco.Web }; var userVals = new Dictionary(); - foreach (var p in from IPublishedProperty p in n.Properties where p.DataValue != null select p) + foreach (var p in from IPublishedContentProperty p in n.Properties where p.DataValue != null select p) { // probably want the "object value" of the property here... userVals[p.PropertyTypeAlias] = p.Value; diff --git a/src/Umbraco.Web/PublishedContentPropertyExtension.cs b/src/Umbraco.Web/PublishedContentPropertyExtension.cs index ee4dd83e57..39f195c541 100644 --- a/src/Umbraco.Web/PublishedContentPropertyExtension.cs +++ b/src/Umbraco.Web/PublishedContentPropertyExtension.cs @@ -11,17 +11,17 @@ namespace Umbraco.Web { #region GetValue - public static T GetValue(this IPublishedProperty property) + public static T GetValue(this IPublishedContentProperty property) { return property.GetValue(false, default(T)); } - public static T GetValue(this IPublishedProperty property, T defaultValue) + public static T GetValue(this IPublishedContentProperty property, T defaultValue) { return property.GetValue(true, defaultValue); } - internal static T GetValue(this IPublishedProperty property, bool withDefaultValue, T defaultValue) + internal static T GetValue(this IPublishedContentProperty property, bool withDefaultValue, T defaultValue) { if (property.HasValue == false && withDefaultValue) return defaultValue; diff --git a/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs b/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs index e30fcedabe..225ae5b3d8 100644 --- a/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs +++ b/src/Umbraco.Web/umbraco.presentation/CompatibilityHelper.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.umbraco.presentation return node; } - private static IProperty ConvertToNodeProperty(IPublishedProperty prop) + private static IProperty ConvertToNodeProperty(IPublishedContentProperty prop) { return new ConvertedProperty(prop); } @@ -118,9 +118,9 @@ namespace Umbraco.Web.umbraco.presentation private class ConvertedProperty : IProperty, IHtmlString { - private readonly IPublishedProperty _prop; + private readonly IPublishedContentProperty _prop; - public ConvertedProperty(IPublishedProperty prop) + public ConvertedProperty(IPublishedContentProperty prop) { _prop = prop; } From b0c5d16ba7f76034b59e1c27be063b192e40638c Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 30 Apr 2014 19:29:32 +0200 Subject: [PATCH 11/19] U4-4127 Turkish culture prevents Macros embedded --- src/Umbraco.Web/UmbracoHelper.cs | 3 ++- src/Umbraco.Web/umbraco.presentation/macro.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 1c0882b9f5..696d17435a 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -160,7 +161,7 @@ namespace Umbraco.Web { //TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method of macro.cs // looks for a lower case match. WTF. the whole macro concept needs to be rewritten. - macroProps.Add(i.Key.ToLower(), i.Value); + macroProps.Add(i.Key.ToLowerInvariant(), i.Value); } var macroControl = m.renderMacro(macroProps, UmbracoContext.Current.PublishedContentRequest.UmbracoPage.Elements, diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index cacf2a13e3..49e49b592f 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -815,9 +815,9 @@ namespace umbraco { foreach (MacroPropertyModel mp in Model.Properties) { - if (attributes.ContainsKey(mp.Key.ToLower())) + if (attributes.ContainsKey(mp.Key.ToLowerInvariant())) { - mp.Value = attributes[mp.Key.ToLower()].ToString(); + mp.Value = attributes[mp.Key.ToLowerInvariant()].ToString(); } else { From f23af8525312e2d86d54c972b519114fefde6ec6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 1 May 2014 11:36:17 +1000 Subject: [PATCH 12/19] Fixes: U4-4624 Media cache hits the DB on every empty property, U4-4338 Umbraco fails to enumerate TypedMedia --- .../XmlPublishedCache/PublishedMediaCache.cs | 79 ++++++++----------- 1 file changed, 31 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 9217a8ac87..7468bf1780 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -120,7 +120,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache try { //by default use the InternalSearcher - return eMgr.IndexProviderCollection["InternalIndexer"]; + var indexer = eMgr.IndexProviderCollection["InternalIndexer"]; + if (indexer.IndexerData.IncludeNodeTypes.Any() || indexer.IndexerData.ExcludeNodeTypes.Any()) + { + LogHelper.Warn("The InternalIndexer for examine is configured incorrectly, it should not list any include/exclude node types or field names, it should simply be configured as: " + ""); + } + return indexer; } catch (Exception ex) { @@ -176,12 +181,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache return ConvertFromSearchResult(results.First()); } } - catch (FileNotFoundException) + catch (FileNotFoundException ex) { //Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco //See this thread: http://examine.cdodeplex.com/discussions/264341 //Catch the exception here for the time being, and just fallback to GetMedia //TODO: Need to fix examine in LB scenarios! + LogHelper.Error("Could not load data from Examine index for media", ex); } } @@ -256,9 +262,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache if (xpath == null) throw new ArgumentNullException("xpath"); var values = new Dictionary {{"nodeName", xpath.GetAttribute("nodeName", "")}}; - if (!UmbracoSettings.UseLegacyXmlSchema) + if (UmbracoSettings.UseLegacyXmlSchema == false) { - values.Add("nodeTypeAlias", xpath.Name); + values["nodeTypeAlias"] = xpath.Name; } var result = xpath.SelectChildren(XPathNodeType.Element); @@ -270,13 +276,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache //checking for duplicate keys because of the 'nodeTypeAlias' might already be added above. if (!values.ContainsKey(result.Current.Name)) { - values.Add(result.Current.Name, result.Current.Value); + values[result.Current.Name] = result.Current.Value; } while (result.Current.MoveToNextAttribute()) { if (!values.ContainsKey(result.Current.Name)) { - values.Add(result.Current.Name, result.Current.Value); + values[result.Current.Name] = result.Current.Value; } } result.Current.MoveToParent(); @@ -295,7 +301,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache value = result.Current.OuterXml; } } - values.Add(result.Current.Name, value); + values[result.Current.Name] = value; } } @@ -319,48 +325,25 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// private IPublishedProperty GetProperty(DictionaryPublishedContent dd, string alias) { - if (dd.LoadedFromExamine) - { - //if this is from Examine, lets check if the alias does not exist on the document - if (dd.Properties.All(x => x.PropertyTypeAlias != alias)) - { - //ok it doesn't exist, we might assume now that Examine didn't index this property because the index is not set up correctly - //so before we go loading this from the database, we can check if the alias exists on the content type at all, this information - //is cached so will be quicker to look up. - if (dd.Properties.Any(x => x.PropertyTypeAlias == UmbracoContentIndexer.NodeTypeAliasFieldName)) - { - // so in dd.Properties, there is an IPublishedProperty with property type alias "__NodeTypeAlias" and - // that special property would contain the node type alias, which we use to get "aliases & names". That - // special property is going to be a PropertyResult (with Value == DataValue) and we - // want its value in the most simple way = it is OK to use DataValue here. - var aliasesAndNames = ContentType.GetAliasesAndNames(dd.Properties.First(x => x.PropertyTypeAlias.InvariantEquals(UmbracoContentIndexer.NodeTypeAliasFieldName)).DataValue.ToString()); - if (aliasesAndNames != null) - { - if (!aliasesAndNames.ContainsKey(alias)) - { - //Ok, now we know it doesn't exist on this content type anyways - return null; - } - } - } + //lets check if the alias does not exist on the document. + //NOTE: Examine will not index empty values and we do not output empty XML Elements to the cache - either of these situations + // would mean that the property is missing from the collection whether we are getting the value from Examine or from the library media cache. + if (dd.Properties.All(x => x.PropertyTypeAlias != alias)) + { + return null; + } - //if we've made it here, that means it does exist on the content type but not in examine, we'll need to query the db :( - var media = global::umbraco.library.GetMedia(dd.Id, true); - if (media != null && media.Current != null) - { - media.MoveNext(); - var mediaDoc = ConvertFromXPathNavigator(media.Current); - return mediaDoc.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); - } - } - } - - //We've made it here which means that the value is stored in the Examine index. - //We are going to check for a special field however, that is because in some cases we store a 'Raw' - //value in the index such as for xml/html. - var rawValue = dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(UmbracoContentIndexer.RawFieldPrefix + alias)); - return rawValue - ?? dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); + if (dd.LoadedFromExamine) + { + //We are going to check for a special field however, that is because in some cases we store a 'Raw' + //value in the index such as for xml/html. + var rawValue = dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(UmbracoContentIndexer.RawFieldPrefix + alias)); + return rawValue + ?? dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); + } + + //if its not loaded from examine, then just return the property + return dd.Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias)); } /// From c4603ee5cdfdbed46856765d2c23a90bb6c18fcb Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 1 May 2014 12:43:40 +1000 Subject: [PATCH 13/19] Fixes: U4-4798 When new property types are added, the internal Examine index isn't notified and will ignore them --- src/Umbraco.Web/Search/ExamineEvents.cs | 20 ++++++ .../Config/IndexSetExtensions.cs | 69 ++++++++++--------- src/UmbracoExamine/UmbracoContentIndexer.cs | 13 ++++ 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Web/Search/ExamineEvents.cs b/src/Umbraco.Web/Search/ExamineEvents.cs index a015761481..a3660b887a 100644 --- a/src/Umbraco.Web/Search/ExamineEvents.cs +++ b/src/Umbraco.Web/Search/ExamineEvents.cs @@ -61,6 +61,7 @@ namespace Umbraco.Web.Search CacheRefresherBase.CacheUpdated += PublishedPageCacheRefresherCacheUpdated; CacheRefresherBase.CacheUpdated += MediaCacheRefresherCacheUpdated; CacheRefresherBase.CacheUpdated += MemberCacheRefresherCacheUpdated; + CacheRefresherBase.CacheUpdated += ContentTypeCacheRefresherCacheUpdated; var contentIndexer = ExamineManager.Instance.IndexProviderCollection["InternalIndexer"] as UmbracoContentIndexer; if (contentIndexer != null) @@ -74,6 +75,25 @@ namespace Umbraco.Web.Search } } + /// + /// This is used to refresh content indexers IndexData based on the DataService whenever a content type is changed since + /// properties may have been added/removed + /// + /// + /// + /// + /// See: http://issues.umbraco.org/issue/U4-4798 + /// + [SecuritySafeCritical] + static void ContentTypeCacheRefresherCacheUpdated(ContentTypeCacheRefresher sender, CacheRefresherEventArgs e) + { + var indexersToUpdated = ExamineManager.Instance.IndexProviderCollection.OfType(); + foreach (var provider in indexersToUpdated) + { + provider.RefreshIndexerDataFromDataService(); + } + } + [SecuritySafeCritical] static void MemberCacheRefresherCacheUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs e) { diff --git a/src/UmbracoExamine/Config/IndexSetExtensions.cs b/src/UmbracoExamine/Config/IndexSetExtensions.cs index 76a4d46575..ac432b16ec 100644 --- a/src/UmbracoExamine/Config/IndexSetExtensions.cs +++ b/src/UmbracoExamine/Config/IndexSetExtensions.cs @@ -14,58 +14,63 @@ namespace UmbracoExamine.Config /// public static class IndexSetExtensions { - - private static readonly object Locker = new object(); - internal static IIndexCriteria ToIndexCriteria(this IndexSet set, IDataService svc, IEnumerable indexFieldPolicies) { + + var attributeFields = set.IndexAttributeFields.Cast().ToArray(); + var userFields = set.IndexUserFields.Cast().ToArray(); + var includeNodeTypes = set.IncludeNodeTypes.ToList().Select(x => x.Name).ToArray(); + var excludeNodeTypes = set.ExcludeNodeTypes.ToList().Select(x => x.Name).ToArray(); + var parentId = set.IndexParentId; + + //if there are no user fields defined, we'll populate them from the data source (include them all) if (set.IndexUserFields.Count == 0) { - lock (Locker) + //we need to add all user fields to the collection if it is empty (this is the default if none are specified) + var userProps = svc.ContentService.GetAllUserPropertyNames(); + var fields = new List(); + foreach (var u in userProps) { - //we need to add all user fields to the collection if it is empty (this is the default if none are specified) - var userFields = svc.ContentService.GetAllUserPropertyNames(); - foreach (var u in userFields) + var field = new IndexField() { Name = u }; + var policy = indexFieldPolicies.FirstOrDefault(x => x.Name == u); + if (policy != null) { - var field = new IndexField() {Name = u}; - var policy = indexFieldPolicies.FirstOrDefault(x => x.Name == u); - if (policy != null) - { - field.Type = policy.Type; - field.EnableSorting = policy.EnableSorting; - } - set.IndexUserFields.Add(field); + field.Type = policy.Type; + field.EnableSorting = policy.EnableSorting; } + fields.Add(field); } + userFields = fields.ToArray(); } + //if there are no attribute fields defined, we'll populate them from the data source (include them all) if (set.IndexAttributeFields.Count == 0) { - lock (Locker) + //we need to add all system fields to the collection if it is empty (this is the default if none are specified) + var sysProps = svc.ContentService.GetAllSystemPropertyNames(); + var fields = new List(); + foreach (var s in sysProps) { - //we need to add all system fields to the collection if it is empty (this is the default if none are specified) - var sysFields = svc.ContentService.GetAllSystemPropertyNames(); - foreach (var s in sysFields) + var field = new IndexField() { Name = s }; + var policy = indexFieldPolicies.FirstOrDefault(x => x.Name == s); + if (policy != null) { - var field = new IndexField() { Name = s }; - var policy = indexFieldPolicies.FirstOrDefault(x => x.Name == s); - if (policy != null) - { - field.Type = policy.Type; - field.EnableSorting = policy.EnableSorting; - } - set.IndexAttributeFields.Add(field); + field.Type = policy.Type; + field.EnableSorting = policy.EnableSorting; } + fields.Add(field); } + attributeFields = fields.ToArray(); } + return new IndexCriteria( - set.IndexAttributeFields.Cast().ToArray(), - set.IndexUserFields.Cast().ToArray(), - set.IncludeNodeTypes.ToList().Select(x => x.Name).ToArray(), - set.ExcludeNodeTypes.ToList().Select(x => x.Name).ToArray(), - set.IndexParentId); + attributeFields, + userFields, + includeNodeTypes, + excludeNodeTypes, + parentId); } /// diff --git a/src/UmbracoExamine/UmbracoContentIndexer.cs b/src/UmbracoExamine/UmbracoContentIndexer.cs index 9da53a77f2..3f442f5daa 100644 --- a/src/UmbracoExamine/UmbracoContentIndexer.cs +++ b/src/UmbracoExamine/UmbracoContentIndexer.cs @@ -298,6 +298,19 @@ namespace UmbracoExamine base.RebuildIndex(); } + /// + /// Used to refresh the current IndexerData from the data in the DataService. This can be used + /// if there are more properties added/removed from the database + /// + public void RefreshIndexerDataFromDataService() + { + //TODO: This would be much better done if the IndexerData property had read/write locks applied + // to it! Unless we update the base class there's really no way to prevent the IndexerData from being + // changed during an operation that is reading from it. + var newIndexerData = GetIndexerData(IndexSets.Instance.Sets[IndexSetName]); + IndexerData = newIndexerData; + } + /// /// Override this method to strip all html from all user fields before raising the event, then after the event /// ensure our special Path field is added to the collection From c139c5d93e969a2de1ce9079bf5737e8316e2e4b Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 1 May 2014 09:55:03 +0200 Subject: [PATCH 14/19] U4-3925 Cancel Document_BeforePublish event gives YSOD --- src/umbraco.cms/businesslogic/web/Document.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 51ecb20967..6255a7b2eb 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -1025,10 +1025,10 @@ namespace umbraco.cms.businesslogic.web return result; } - return Attempt.Fail(); + return new Attempt(false, new PublishStatus(Content, PublishStatusType.FailedCancelledByEvent)); } - return Attempt.Fail(); + return new Attempt(false, new PublishStatus(Content, PublishStatusType.FailedCancelledByEvent)); } /// From 851961ef2ba8c428f9cbd31a043fe90328c8d4fd Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 1 May 2014 10:48:27 +0200 Subject: [PATCH 15/19] U4-4775 creating new member group shows error message in dialog... --- src/Umbraco.Core/EnumerableExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs index 525f75e709..45882872c3 100644 --- a/src/Umbraco.Core/EnumerableExtensions.cs +++ b/src/Umbraco.Core/EnumerableExtensions.cs @@ -118,7 +118,8 @@ namespace Umbraco.Core { foreach (TItem item in items) { - action(item); + if(item != null) + action(item); } } From e858f4ff1ea60a2d091b3d8715fcbdee2b9e4b5e Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 1 May 2014 11:45:14 +0200 Subject: [PATCH 16/19] U4-4775 creating new member group shows error message in dialog... --- src/Umbraco.Core/EnumerableExtensions.cs | 3 +-- .../Persistence/Repositories/MemberGroupRepository.cs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs index 45882872c3..525f75e709 100644 --- a/src/Umbraco.Core/EnumerableExtensions.cs +++ b/src/Umbraco.Core/EnumerableExtensions.cs @@ -118,8 +118,7 @@ namespace Umbraco.Core { foreach (TItem item in items) { - if(item != null) - action(item); + action(item); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs index e0997967bc..ef1790033c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs @@ -120,7 +120,8 @@ namespace Umbraco.Core.Persistence.Repositories group.AddingEntity(); var dto = _modelFactory.BuildDto(group); var o = Database.IsNew(dto) ? Convert.ToInt32(Database.Insert(dto)) : Database.Update(dto); - + group.Id = dto.NodeId; //Set Id on entity to ensure an Id is set + //Update with new correct path dto.Path = string.Concat("-1,", dto.NodeId); Database.Update(dto); From caf41b74b8fcacc575c274a9163be58cdef5c846 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 1 May 2014 12:26:18 +0200 Subject: [PATCH 17/19] Add failing test - dictionary items don't get properly nested --- .../Services/Importing/PackageImportTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index e920a4e34f..4a318f4603 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -402,6 +402,32 @@ namespace Umbraco.Tests.Services.Importing AssertDictionaryItem("Child", expectedNorwegianChildValue, "nb-NO"); } + [Test] + public void PackagingService_Can_Import_Nested_DictionaryItems() + { + // Arrange + const string parentKey = "Parent"; + const string childKey = "Child"; + + var newPackageXml = XElement.Parse(ImportResources.Dictionary_Package); + var dictionaryItemsElement = newPackageXml.Elements("DictionaryItems").First(); + + AddLanguages(); + + // Act + ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); + + // Assert + Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(parentKey), "DictionaryItem parentKey does not exist"); + Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(childKey), "DictionaryItem childKey does not exist"); + + var parentDictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey(parentKey); + var childDictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey(childKey); + + Assert.That(parentDictionaryItem.ParentId, Is.Not.EqualTo(childDictionaryItem.ParentId)); + Assert.That(childDictionaryItem.ParentId, Is.EqualTo(parentDictionaryItem.Id)); + } + [Test] public void PackagingService_WhenExistingDictionaryKey_ImportsNewChildren() { From 5a862f5c644b80f4dd9902155ba7da78a9d3ee7c Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 1 May 2014 13:51:33 +0200 Subject: [PATCH 18/19] Fixes import of nested dictionary items #U4-4663 --- src/Umbraco.Core/Services/PackagingService.cs | 14 +++++++------- .../Services/Importing/PackageImportTests.cs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 5330507fd4..b02b765a37 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -768,15 +768,15 @@ namespace Umbraco.Core.Services return ImportDictionaryItems(dictionaryItemElementList, languages); } - private IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, List languages) + private IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, List languages, Guid? parentId = null) { var items = new List(); foreach (var dictionaryItemElement in dictionaryItemElementList.Elements("DictionaryItem")) - items.AddRange(ImportDictionaryItem(dictionaryItemElement, languages)); + items.AddRange(ImportDictionaryItem(dictionaryItemElement, languages, parentId)); return items; } - private IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, List languages) + private IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, List languages, Guid? parentId) { var items = new List(); @@ -785,10 +785,10 @@ namespace Umbraco.Core.Services if (_localizationService.DictionaryItemExists(key)) dictionaryItem = GetAndUpdateDictionaryItem(key, dictionaryItemElement, languages); else - dictionaryItem = CreateNewDictionaryItem(key, dictionaryItemElement, languages); + dictionaryItem = CreateNewDictionaryItem(key, dictionaryItemElement, languages, parentId); _localizationService.Save(dictionaryItem); items.Add(dictionaryItem); - items.AddRange(ImportDictionaryItems(dictionaryItemElement, languages)); + items.AddRange(ImportDictionaryItems(dictionaryItemElement, languages, dictionaryItem.Key)); return items; } @@ -802,9 +802,9 @@ namespace Umbraco.Core.Services return dictionaryItem; } - private static DictionaryItem CreateNewDictionaryItem(string key, XElement dictionaryItemElement, List languages) + private static DictionaryItem CreateNewDictionaryItem(string key, XElement dictionaryItemElement, List languages, Guid? parentId) { - var dictionaryItem = new DictionaryItem(key); + var dictionaryItem = parentId.HasValue ? new DictionaryItem(parentId.Value, key) : new DictionaryItem(key); var translations = new List(); foreach (var valueElement in dictionaryItemElement.Elements("Value")) diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 4a318f4603..1deec4282b 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -415,7 +415,7 @@ namespace Umbraco.Tests.Services.Importing AddLanguages(); // Act - ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); + var dictionaryItems = ServiceContext.PackagingService.ImportDictionaryItems(dictionaryItemsElement); // Assert Assert.That(ServiceContext.LocalizationService.DictionaryItemExists(parentKey), "DictionaryItem parentKey does not exist"); @@ -425,7 +425,7 @@ namespace Umbraco.Tests.Services.Importing var childDictionaryItem = ServiceContext.LocalizationService.GetDictionaryItemByKey(childKey); Assert.That(parentDictionaryItem.ParentId, Is.Not.EqualTo(childDictionaryItem.ParentId)); - Assert.That(childDictionaryItem.ParentId, Is.EqualTo(parentDictionaryItem.Id)); + Assert.That(childDictionaryItem.ParentId, Is.EqualTo(parentDictionaryItem.Key)); } [Test] From 16d98488e4c8178a8193306df6c7f7c295f478e3 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 1 May 2014 14:06:28 +0200 Subject: [PATCH 19/19] Losen up the requirement for json.net dependency --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index 56bf97a8c8..48c82d445c 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -28,7 +28,7 @@ - +