diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs
index dbfd446c39..105d006656 100644
--- a/src/Umbraco.Core/DatabaseContext.cs
+++ b/src/Umbraco.Core/DatabaseContext.cs
@@ -472,6 +472,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)
{
@@ -484,8 +489,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();
@@ -536,9 +542,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();
@@ -565,6 +571,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)
@@ -588,7 +611,7 @@ namespace Umbraco.Core
"the documentation on the subject
";
}
return string.Empty;
- }
+ }*/
private Attempt CheckReadyForInstall()
{
diff --git a/src/Umbraco.Core/Dynamics/PropertyResult.cs b/src/Umbraco.Core/Dynamics/PropertyResult.cs
index d1007f8bb7..60a699969e 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/Template.cs b/src/Umbraco.Core/Models/Template.cs
index d5069e27b3..fc10c818ef 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
{
@@ -35,7 +36,7 @@ namespace Umbraco.Core.Models
base.Path = path;
ParentId = -1;
_name = name; //.Replace("/", ".").Replace("\\", ""); // why? that's just the name!
- _alias = alias.ToSafeAlias();
+ _alias = alias.ToCleanString(CleanStringType.UnderscoreAlias);
}
[DataMember]
diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs
index 7ad88f0739..58a0a47802 100644
--- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs
+++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs
@@ -175,6 +175,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/Migrations/Initial/DatabaseSchemaResult.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs
index 9151ffd598..33595e3905 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/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs
index cacfd87fbd..f9bf78ae2a 100644
--- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs
+++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs
@@ -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, _currentVersion, _targetVersion, true), this))
return false;
//Loop through migrations to generate sql
var migrationContext = InitializeMigrations(migrations, database, databaseProvider, isUpgrade);
-
+
try
{
ExecuteMigrations(migrationContext, database);
@@ -86,8 +86,8 @@ namespace Umbraco.Core.Persistence.Migrations
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,7 +148,7 @@ 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
@@ -158,17 +158,17 @@ namespace Umbraco.Core.Persistence.Migrations
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
+ let migrationAttributes = migration.GetType().GetCustomAttributes(false)
+ from migrationAttribute in migrationAttributes
+ where migrationAttribute != null
+ where
migrationAttribute.TargetVersion > _currentVersion &&
- migrationAttribute.TargetVersion <= _targetVersion &&
+ 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();
+ orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder ascending
+ select migration).Distinct();
return migrations;
}
@@ -180,17 +180,17 @@ namespace Umbraco.Core.Persistence.Migrations
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
+ let migrationAttributes = migration.GetType().GetCustomAttributes(false)
+ from migrationAttribute in migrationAttributes
+ where migrationAttribute != null
+ where
migrationAttribute.TargetVersion > _currentVersion &&
- migrationAttribute.TargetVersion <= _targetVersion &&
+ 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();
+ 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 a972b7eeb0..027cecca9d 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("7.1.0", 0, GlobalSettings.UmbracoMigrationName)]
[Migration("6.2.0", 0, GlobalSettings.UmbracoMigrationName)]
@@ -15,15 +16,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/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index ae5e4f9010..b38b19a2d8 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -158,12 +158,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 ec5f810152..26df451f62 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 3d6f242ecf..789a583510 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
@@ -142,12 +142,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/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs
index 8e051e77e5..0d6fc90016 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 and id
dto.Path = string.Concat("-1,", dto.NodeId);
Database.Update(dto);
diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
index 8f588dcaee..595fcb033d 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
@@ -189,8 +189,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 2ea9814f26..0e91cc3c9e 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 258d26bc91..91cea2ed18 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 63042f0284..34775df456 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"
};
diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs
index 9a8106d633..475d5d185b 100644
--- a/src/Umbraco.Core/Services/PackagingService.cs
+++ b/src/Umbraco.Core/Services/PackagingService.cs
@@ -943,11 +943,12 @@ namespace Umbraco.Core.Services
return ImportDictionaryItems(dictionaryItemElementList, languages, raiseEvents);
}
- private IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, List languages, bool raiseEvents)
+ private IEnumerable ImportDictionaryItems(XElement dictionaryItemElementList, List languages, bool raiseEvents, Guid? parentId = null)
{
var items = new List();
foreach (var dictionaryItemElement in dictionaryItemElementList.Elements("DictionaryItem"))
- items.AddRange(ImportDictionaryItem(dictionaryItemElement, languages, raiseEvents));
+ items.AddRange(ImportDictionaryItem(dictionaryItemElement, languages, raiseEvents, parentId));
+
if (raiseEvents)
ImportedDictionaryItem.RaiseEvent(new ImportEventArgs(items, dictionaryItemElementList, false), this);
@@ -955,7 +956,7 @@ namespace Umbraco.Core.Services
return items;
}
- private IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, List languages, bool raiseEvents)
+ private IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, List languages, bool raiseEvents, Guid? parentId)
{
var items = new List();
@@ -964,10 +965,11 @@ 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, raiseEvents));
+
+ items.AddRange(ImportDictionaryItems(dictionaryItemElement, languages, raiseEvents, dictionaryItem.Key));
return items;
}
@@ -981,9 +983,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.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 84233e59bf..7c29a7aeef 100644
--- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
+++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
@@ -175,6 +175,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.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index d68ca62ddc..5c1e79f449 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -342,6 +342,7 @@
+
@@ -373,6 +374,7 @@
+
@@ -955,7 +957,6 @@
-
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
diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs
index a730b184c4..bec18c23c3 100644
--- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs
+++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs
@@ -414,6 +414,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
+ var dictionaryItems = 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.Key));
+ }
+
[Test]
public void PackagingService_WhenExistingDictionaryKey_ImportsNewChildren()
{
diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
index 8cf3fd5d13..dee2c47751 100644
--- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
+++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
@@ -121,7 +121,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)
{
@@ -177,12 +182,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);
}
}
@@ -259,7 +265,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
var values = new Dictionary {{"nodeName", xpath.GetAttribute("nodeName", "")}};
if (!UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema)
{
- values.Add("nodeTypeAlias", xpath.Name);
+ values["nodeTypeAlias"] = xpath.Name;
}
var result = xpath.SelectChildren(XPathNodeType.Element);
@@ -271,13 +277,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();
@@ -296,7 +302,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
value = result.Current.OuterXml;
}
}
- values.Add(result.Current.Name, value);
+ values[result.Current.Name] = value;
}
}
@@ -320,48 +326,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));
}
///
diff --git a/src/Umbraco.Web/Search/ExamineEvents.cs b/src/Umbraco.Web/Search/ExamineEvents.cs
index c272c7ff14..ed1e01f407 100644
--- a/src/Umbraco.Web/Search/ExamineEvents.cs
+++ b/src/Umbraco.Web/Search/ExamineEvents.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Globalization;
using System.Linq;
using System.Security;
@@ -60,6 +60,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)
@@ -73,6 +74,24 @@ 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
+ ///
+ static void ContentTypeCacheRefresherCacheUpdated(ContentTypeCacheRefresher sender, CacheRefresherEventArgs e)
+ {
+ var indexersToUpdated = ExamineManager.Instance.IndexProviderCollection.OfType();
+ foreach (var provider in indexersToUpdated)
+ {
+ provider.RefreshIndexerDataFromDataService();
+ }
+ }
+
static void MemberCacheRefresherCacheUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs e)
{
switch (e.MessageType)
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index 702d74346d..bfa57d5ab3 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;
@@ -254,7 +255,7 @@ namespace Umbraco.Web
//NOTE: the value could have html encoded values, so we need to deal with that
- macroProps.Add(i.Key.ToLower(), (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value);
+ macroProps.Add(i.Key.ToLowerInvariant(), (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value);
}
var macroControl = m.renderMacro(macroProps,
umbracoPage.Elements,
diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs
index 870522fc6d..2fd71b1458 100644
--- a/src/Umbraco.Web/umbraco.presentation/macro.cs
+++ b/src/Umbraco.Web/umbraco.presentation/macro.cs
@@ -803,9 +803,9 @@ namespace umbraco
{
foreach (MacroPropertyModel mp in Model.Properties)
{
- if (attributes.ContainsKey(mp.Key.ToLower()))
+ if (attributes.ContainsKey(mp.Key.ToLowerInvariant()))
{
- var item = attributes[mp.Key.ToLower()];
+ var item = attributes[mp.Key.ToLowerInvariant()];
mp.Value = item == null ? string.Empty : item.ToString();
}
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
diff --git a/src/umbraco.cms/businesslogic/template/Template.cs b/src/umbraco.cms/businesslogic/template/Template.cs
index 6d09bd37a7..12b59d7138 100644
--- a/src/umbraco.cms/businesslogic/template/Template.cs
+++ b/src/umbraco.cms/businesslogic/template/Template.cs
@@ -7,6 +7,7 @@ using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
+using Umbraco.Core.Strings;
using umbraco.DataLayer;
using System.Text.RegularExpressions;
using System.IO;
@@ -205,7 +206,7 @@ namespace umbraco.cms.businesslogic.template
{
FlushCache();
_oldAlias = _alias;
- _alias = value.ToSafeAlias();
+ _alias = value.ToCleanString(CleanStringType.UnderscoreAlias);
SqlHelper.ExecuteNonQuery("Update cmsTemplate set alias = @alias where NodeId = " + this.Id, SqlHelper.CreateParameter("@alias", _alias));
_templateAliasesInitialized = false;
@@ -403,13 +404,13 @@ namespace umbraco.cms.businesslogic.template
var node = MakeNew(-1, ObjectType, u.Id, 1, name, Guid.NewGuid());
//ensure unique alias
- name = name.ToSafeAlias();
+ name = name.ToCleanString(CleanStringType.UnderscoreAlias);
if (GetByAlias(name) != null)
name = EnsureUniqueAlias(name, 1);
//name = name.Replace("/", ".").Replace("\\", ""); //why? ToSafeAlias() already removes those chars
if (name.Length > 100)
- name = name.Substring(0, 98); // + "..."; // no, these are invalid alias chars
+ 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)",
SqlHelper.CreateParameter("@nodeId", node.Id),
diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs
index 98e7db6647..098d3c87ed 100644
--- a/src/umbraco.cms/businesslogic/web/Document.cs
+++ b/src/umbraco.cms/businesslogic/web/Document.cs
@@ -1022,10 +1022,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));
}
///