diff --git a/src/Umbraco.Core/Models/TaggableObjectTypes.cs b/src/Umbraco.Core/Models/TaggableObjectTypes.cs index be019410e5..ae54bc02bd 100644 --- a/src/Umbraco.Core/Models/TaggableObjectTypes.cs +++ b/src/Umbraco.Core/Models/TaggableObjectTypes.cs @@ -5,6 +5,7 @@ /// public enum TaggableObjectTypes { + All, Content, Media, Member diff --git a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs index 344d9f4c43..ac39d9556e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs @@ -168,8 +168,6 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup) { - var nodeObjectType = GetNodeObjectType(objectType); - var sql = new Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("group")) .From() @@ -181,17 +179,21 @@ namespace Umbraco.Core.Persistence.Repositories .On(left => left.Id, right => right.PropertyTypeId) .InnerJoin() .On(left => left.NodeId, right => right.NodeId) - .Where(dto => dto.NodeObjectType == nodeObjectType) .Where(dto => dto.Group == tagGroup); + if (objectType != TaggableObjectTypes.All) + { + var nodeObjectType = GetNodeObjectType(objectType); + sql = sql + .Where(dto => dto.NodeObjectType == nodeObjectType); + } + return CreateTaggedEntityCollection( ApplicationContext.Current.DatabaseContext.Database.Fetch(sql)); } public IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null) { - var nodeObjectType = GetNodeObjectType(objectType); - var sql = new Sql() .Select("cmsTagRelationship.nodeId, cmsPropertyType.Alias, cmsPropertyType.id as propertyTypeId, cmsTags.tag, cmsTags.id as tagId, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("group")) .From() @@ -203,9 +205,15 @@ namespace Umbraco.Core.Persistence.Repositories .On(left => left.Id, right => right.PropertyTypeId) .InnerJoin() .On(left => left.NodeId, right => right.NodeId) - .Where(dto => dto.NodeObjectType == nodeObjectType) .Where(dto => dto.Tag == tag); + if (objectType != TaggableObjectTypes.All) + { + var nodeObjectType = GetNodeObjectType(objectType); + sql = sql + .Where(dto => dto.NodeObjectType == nodeObjectType); + } + if (tagGroup.IsNullOrWhiteSpace() == false) { sql = sql.Where(dto => dto.Group == tagGroup); @@ -233,8 +241,6 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, string group = null) { - var nodeObjectType = GetNodeObjectType(objectType); - var sql = GetTagsQuerySelect(true); sql = ApplyRelationshipJoinToTagsQuery(sql); @@ -243,8 +249,14 @@ namespace Umbraco.Core.Persistence.Repositories .InnerJoin() .On(left => left.NodeId, right => right.NodeId) .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) - .Where(dto => dto.NodeObjectType == nodeObjectType); + .On(left => left.NodeId, right => right.NodeId); + + if (objectType != TaggableObjectTypes.All) + { + var nodeObjectType = GetNodeObjectType(objectType); + sql = sql + .Where(dto => dto.NodeObjectType == nodeObjectType); + } sql = ApplyGroupFilterToTagsQuery(sql, group); diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index caed3928ef..1b2111a15e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -430,7 +430,7 @@ namespace Umbraco.Core.Persistence.Repositories string content; using (var stream = _viewsFileSystem.OpenFile(fileName)) - using (var reader = new StreamReader(stream, Encoding.UTF8)) + using (var reader = new StreamReader(stream, Encoding.UTF8, true)) { content = reader.ReadToEnd(); } @@ -441,9 +441,9 @@ namespace Umbraco.Core.Persistence.Repositories private void PopulateMasterpageTemplate(ITemplate template, string fileName) { string content; - + using (var stream = _masterpagesFileSystem.OpenFile(fileName)) - using (var reader = new StreamReader(stream, Encoding.UTF8)) + using (var reader = new StreamReader(stream, Encoding.UTF8, true)) { content = reader.ReadToEnd(); } diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 559bf100d0..5a77956931 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -53,6 +53,14 @@ namespace Umbraco.Core.Services /// Alias of the section to remove void DeleteSectionFromAllUsers(string sectionAlias); + /// + /// Add a specific section to all users or those specified as parameters + /// + /// This is useful when a new section is created to allow specific users accessing it + /// Alias of the section to add + /// Specifiying nothing will add the section to all user + void AddSectionToAllUsers(string sectionAlias, params int[] userIds); + /// /// Get permissions set for a user and optional node ids /// @@ -117,4 +125,4 @@ namespace Umbraco.Core.Services #endregion } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Services/LocalizedTextService.cs b/src/Umbraco.Core/Services/LocalizedTextService.cs index f5c2cc033a..c9d05f3a3b 100644 --- a/src/Umbraco.Core/Services/LocalizedTextService.cs +++ b/src/Umbraco.Core/Services/LocalizedTextService.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Xml; using System.Xml.Linq; using System.Xml.XPath; +using Umbraco.Core.Logging; namespace Umbraco.Core.Services { @@ -80,7 +81,8 @@ namespace Umbraco.Core.Services { if (_xmlSource.ContainsKey(culture) == false) { - throw new NullReferenceException("The culture specified " + culture + " was not found in any configured sources for this service"); + LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + return result; } //convert all areas + keys to a single key with a '/' @@ -103,7 +105,8 @@ namespace Umbraco.Core.Services { if (_dictionarySource.ContainsKey(culture) == false) { - throw new NullReferenceException("The culture specified " + culture + " was not found in any configured sources for this service"); + LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + return result; } //convert all areas + keys to a single key with a '/' @@ -137,7 +140,8 @@ namespace Umbraco.Core.Services { if (_dictionarySource.ContainsKey(culture) == false) { - throw new NullReferenceException("The culture specified " + culture + " was not found in any configured sources for this service"); + LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + return "[" + key + "]"; } var cultureSource = _dictionarySource[culture]; @@ -174,7 +178,8 @@ namespace Umbraco.Core.Services { if (_xmlSource.ContainsKey(culture) == false) { - throw new NullReferenceException("The culture specified " + culture + " was not found in any configured sources for this service"); + LogHelper.Warn("The culture specified {0} was not found in any configured sources for this service", () => culture); + return "[" + key + "]"; } var cultureSource = _xmlSource[culture].Value; diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs index 147a3cda31..30e43a694c 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Xml.Linq; using Umbraco.Core.Cache; +using Umbraco.Core.Logging; namespace Umbraco.Core.Services { @@ -20,7 +21,15 @@ namespace Umbraco.Core.Services if (cache == null) throw new ArgumentNullException("cache"); if (fileSourceFolder == null) throw new ArgumentNullException("fileSourceFolder"); _cache = cache; - _fileSourceFolder = fileSourceFolder; + + if (fileSourceFolder.Exists == false) + { + LogHelper.Warn("The folder does not exist: {0}, therefore no sources will be discovered", () => fileSourceFolder.FullName); + } + else + { + _fileSourceFolder = fileSourceFolder; + } } /// @@ -30,6 +39,9 @@ namespace Umbraco.Core.Services public IDictionary> GetXmlSources() { var result = new Dictionary>(); + + if (_fileSourceFolder == null) return result; + foreach (var fileInfo in _fileSourceFolder.GetFiles("*.xml")) { var localCopy = fileInfo; diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index cf477a125b..a1339ce360 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -133,14 +133,7 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateTagRepository(_uowProvider.GetUnitOfWork())) { - if (tagGroup.IsNullOrWhiteSpace()) - { - return repository.GetAll(); - } - - var query = Query.Builder.Where(x => x.Group == tagGroup); - var definitions = repository.GetByQuery(query); - return definitions; + return repository.GetTagsForEntityType(TaggableObjectTypes.All, tagGroup); } } diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index 1a523835c8..9be1ce0d11 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -672,6 +672,36 @@ namespace Umbraco.Core.Services uow.Commit(); } } + + /// + /// Add a specific section to all users or those specified as parameters + /// + /// This is useful when a new section is created to allow specific users accessing it + /// Alias of the section to add + /// Specifiying nothing will add the section to all user + public void AddSectionToAllUsers(string sectionAlias, params int[] userIds) + { + var uow = _uowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateUserRepository(uow)) + { + IEnumerable users; + if (userIds.Any()) + { + users = repository.GetAll(userIds); + } + else + { + users = repository.GetAll(); + } + foreach (var user in users.Where(u => !u.AllowedSections.InvariantContains(sectionAlias))) + { + //now add the section for each user and commit + user.AddAllowedSection(sectionAlias); + repository.AddOrUpdate(user); + } + uow.Commit(); + } + } /// /// Get permissions set for a user and optional node ids @@ -745,4 +775,4 @@ namespace Umbraco.Core.Services /// public static event TypedEventHandler> DeletedUserType; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs b/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs index c86ee01100..43e5d0fcf9 100644 --- a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs @@ -7,7 +7,7 @@ using Umbraco.Core.ObjectResolution; namespace Umbraco.Tests.CoreStrings { - [TestFixture] + [TestFixture] public class StringExtensionsTests { [SetUp] diff --git a/src/Umbraco.Tests/CoreStrings/StringValidationTests.cs b/src/Umbraco.Tests/CoreStrings/StringValidationTests.cs new file mode 100644 index 0000000000..c1f8b92438 --- /dev/null +++ b/src/Umbraco.Tests/CoreStrings/StringValidationTests.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; +using NUnit.Framework; + +namespace Umbraco.Tests.CoreStrings +{ + [TestFixture] + public class StringValidationTests + { + [Test] + public void Validate_Email_Address() + { + var foo = new EmailAddressAttribute(); + + Assert.IsTrue(foo.IsValid("someone@somewhere.com")); + Assert.IsTrue(foo.IsValid("someone@somewhere.co.uk")); + Assert.IsTrue(foo.IsValid("someone+tag@somewhere.net")); + Assert.IsTrue(foo.IsValid("futureTLD@somewhere.fooo")); + + Assert.IsTrue(foo.IsValid("abc@xyz.financial")); + + Assert.IsFalse(foo.IsValid("fdsa")); + Assert.IsFalse(foo.IsValid("fdsa@")); + Assert.IsFalse(foo.IsValid("fdsa@fdsa")); + Assert.IsFalse(foo.IsValid("fdsa@fdsa.")); + + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index bd35197193..c3524580dd 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -658,14 +658,20 @@ namespace Umbraco.Tests.Persistence.Repositories new[] { new Tag {Text = "tag1", Group = "test"}, - new Tag {Text = "tag2", Group = "test1"} + new Tag {Text = "tag4", Group = "test1"} }, false); var result1 = repository.GetTagsForEntityType(TaggableObjectTypes.Content).ToArray(); var result2 = repository.GetTagsForEntityType(TaggableObjectTypes.Media).ToArray(); + var result3 = repository.GetTagsForEntityType(TaggableObjectTypes.All).ToArray(); Assert.AreEqual(3, result1.Count()); Assert.AreEqual(2, result2.Count()); + Assert.AreEqual(4, result3.Count()); + + Assert.AreEqual(1, result1.Single(x => x.Text == "tag1").NodeCount); + Assert.AreEqual(2, result3.Single(x => x.Text == "tag1").NodeCount); + Assert.AreEqual(1, result3.Single(x => x.Text == "tag4").NodeCount); } } diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index 2a099c9001..f3100aa133 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -451,6 +451,43 @@ namespace Umbraco.Tests.Services } + [Test] + public void Can_Add_Section_To_All_Users() + { + var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); + + var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); + var user2 = ServiceContext.UserService.CreateUserWithIdentity("test2", "test2@test.com", userType); + var user3 = ServiceContext.UserService.CreateUserWithIdentity("test3", "test3@test.com", userType); + var user4 = ServiceContext.UserService.CreateUserWithIdentity("test4", "test4@test.com", userType); + + //now add the section to specific users + ServiceContext.UserService.AddSectionToAllUsers("test", (int)user1.Id, (int)user2.Id); + + //assert + var result1 = ServiceContext.UserService.GetUserById((int)user1.Id); + var result2 = ServiceContext.UserService.GetUserById((int)user2.Id); + var result3 = ServiceContext.UserService.GetUserById((int)user3.Id); + var result4 = ServiceContext.UserService.GetUserById((int)user4.Id); + Assert.IsTrue(result1.AllowedSections.Contains("test")); + Assert.IsTrue(result2.AllowedSections.Contains("test")); + Assert.IsFalse(result3.AllowedSections.Contains("test")); + Assert.IsFalse(result4.AllowedSections.Contains("test")); + + //now add the section to all users + ServiceContext.UserService.AddSectionToAllUsers("test"); + + //assert + result1 = ServiceContext.UserService.GetUserById((int)user1.Id); + result2 = ServiceContext.UserService.GetUserById((int)user2.Id); + result3 = ServiceContext.UserService.GetUserById((int)user3.Id); + result4 = ServiceContext.UserService.GetUserById((int)user4.Id); + Assert.IsTrue(result1.AllowedSections.Contains("test")); + Assert.IsTrue(result2.AllowedSections.Contains("test")); + Assert.IsTrue(result3.AllowedSections.Contains("test")); + Assert.IsTrue(result4.AllowedSections.Contains("test")); + } + [Test] public void Get_By_Profile_Username() { @@ -512,4 +549,4 @@ namespace Umbraco.Tests.Services Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(0)); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index b6f562f106..60e57f91f0 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -168,6 +168,7 @@ + diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs index cf58f420ca..77a9fd2dba 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexTest.cs @@ -142,12 +142,15 @@ namespace Umbraco.Tests.UmbracoExamine { var s = (IndexSearcher)_searcher.GetSearcher(); + + //first delete all 'Content' (not media). This is done by directly manipulating the index with the Lucene API, not examine! - var r = IndexReader.Open(s.GetIndexReader().Directory(), false); + var contentTerm = new Term(LuceneIndexer.IndexTypeFieldName, IndexTypes.Content); - var delCount = r.DeleteDocuments(contentTerm); - r.Commit(); - r.Close(); + var writer = _indexer.GetIndexWriter(); + writer.DeleteDocuments(contentTerm); + writer.Commit(); + //make sure the content is gone. This is done with lucene APIs, not examine! var collector = new AllHitsCollector(false, true); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/nodirtycheck.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/nodirtycheck.directive.js index 74c007dfbc..f027d7a12f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/nodirtycheck.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/nodirtycheck.directive.js @@ -15,4 +15,4 @@ function noDirtyCheck() { } }; } -angular.module('umbraco.directives').directive("noDirtyCheck", noDirtyCheck); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("noDirtyCheck", noDirtyCheck); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js index b276c8c931..fdcf768947 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js @@ -27,4 +27,4 @@ function valHighlight($timeout) { } }; } -angular.module('umbraco.directives').directive("valHighlight", valHighlight); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valHighlight", valHighlight); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js new file mode 100644 index 0000000000..88ffd6f0fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js @@ -0,0 +1,44 @@ +/** + * @ngdoc directive + * @name umbraco.directives.directive:valEmail + * @restrict A + * @description A custom directive to validate an email address string, this is required because angular's default validator is incorrect. + **/ +function valEmail(valEmailExpression) { + + return { + require: 'ngModel', + restrict: "A", + link: function (scope, elm, attrs, ctrl) { + + var patternValidator = function (viewValue) { + //NOTE: we don't validate on empty values, use required validator for that + if (!viewValue || valEmailExpression.EMAIL_REGEXP.test(viewValue)) { + // it is valid + ctrl.$setValidity('valEmail', true); + //assign a message to the validator + ctrl.errorMsg = ""; + return viewValue; + } + else { + // it is invalid, return undefined (no model update) + ctrl.$setValidity('valEmail', false); + //assign a message to the validator + ctrl.errorMsg = "Invalid email"; + return undefined; + } + }; + + ctrl.$formatters.push(patternValidator); + ctrl.$parsers.push(patternValidator); + } + }; +} + +angular.module('umbraco.directives.validation') + .directive("valEmail", valEmail) + .factory('valEmailExpression', function() { + return { + EMAIL_REGEXP: /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index d20feb0379..1bd4d409e7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -105,4 +105,4 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not } }; } -angular.module('umbraco.directives').directive("valFormManager", valFormManager); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valFormManager", valFormManager); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index d37f4c5271..a8d546bc36 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -182,4 +182,4 @@ function valPropertyMsg(serverValidationManager) { } }; } -angular.module('umbraco.directives').directive("valPropertyMsg", valPropertyMsg); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valPropertyMsg", valPropertyMsg); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js index e98fb06c98..651c0a54c7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js @@ -61,4 +61,4 @@ function valRegex() { } }; } -angular.module('umbraco.directives').directive("valRegex", valRegex); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valRegex", valRegex); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js index c1bcc4fd38..6225485073 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js @@ -91,4 +91,4 @@ function valServer(serverValidationManager) { } }; } -angular.module('umbraco.directives').directive("valServer", valServer); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valServer", valServer); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js index da79253c2f..9a077615df 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js @@ -51,4 +51,4 @@ function valServerField(serverValidationManager) { } }; } -angular.module('umbraco.directives').directive("valServerField", valServerField); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valServerField", valServerField); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js index 0216fe14d7..cd6dc51eca 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js @@ -35,4 +35,4 @@ function valTab() { } }; } -angular.module('umbraco.directives').directive("valTab", valTab); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valTab", valTab); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js index 5a57754524..cdcfbcfe2a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js @@ -84,4 +84,4 @@ function valToggleMsg(serverValidationManager) { * @requires formController * @description This directive will show/hide an error based on: is the value + the given validator invalid? AND, has the form been submitted ? **/ -angular.module('umbraco.directives').directive("valToggleMsg", valToggleMsg); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valToggleMsg", valToggleMsg); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/install.loader.js b/src/Umbraco.Web.UI.Client/src/install.loader.js index 66f00f742c..5415a106e1 100644 --- a/src/Umbraco.Web.UI.Client/src/install.loader.js +++ b/src/Umbraco.Web.UI.Client/src/install.loader.js @@ -7,10 +7,11 @@ LazyLoad.js( [ 'lib/angular/1.1.5/angular-mocks.js', 'lib/angular/1.1.5/angular-sanitize.min.js', 'lib/underscore/underscore-min.js', - 'js/umbraco.installer.js' + 'js/umbraco.installer.js', + 'js/umbraco.directives.js' ], function () { jQuery(document).ready(function () { - angular.bootstrap(document, ['ngSanitize', 'umbraco.install']); + angular.bootstrap(document, ['ngSanitize', 'umbraco.install', 'umbraco.directives.validation']); }); } ); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/user.html b/src/Umbraco.Web.UI.Client/src/installer/steps/user.html index 8202593782..2cd50fe208 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/user.html +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/user.html @@ -18,7 +18,7 @@
- + Your email will be used as your login
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html index f93b4c7a9a..0081d6ac26 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/email/email.html @@ -1,13 +1,14 @@ 
- Required - Invalid email + Invalid email
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/directives/val-email.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/directives/val-email.spec.js new file mode 100644 index 0000000000..265689988d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/test/unit/common/directives/val-email.spec.js @@ -0,0 +1,34 @@ +describe('valEmail directive tests', function() { + + var valEmailExpression; + + beforeEach(module('umbraco')); + + beforeEach(inject(function ($injector) { + //TODO: I have no idea why this doesn't work!!?? it freakin should + //valEmailExpression = $injector.get('valEmailExpression'); + + //in the meantime, i've had to hard code the regex statement here + valEmailExpression = { + EMAIL_REGEXP: /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i + }; + + })); + + describe('EMAIL_REGEXP', function () { + /* global EMAIL_REGEXP: false */ + it('should validate email', function () { + expect(valEmailExpression.EMAIL_REGEXP.test('a@b.com')).toBe(true); + expect(valEmailExpression.EMAIL_REGEXP.test('a@b.museum')).toBe(true); + expect(valEmailExpression.EMAIL_REGEXP.test('a@B.c')).toBe(true); + expect(valEmailExpression.EMAIL_REGEXP.test('a@.b.c')).toBe(false); + expect(valEmailExpression.EMAIL_REGEXP.test('a@-b.c')).toBe(false); + expect(valEmailExpression.EMAIL_REGEXP.test('a@b-.c')).toBe(false); + expect(valEmailExpression.EMAIL_REGEXP.test('a@3b.c')).toBe(true); + expect(valEmailExpression.EMAIL_REGEXP.test('a@b')).toBe(true); + expect(valEmailExpression.EMAIL_REGEXP.test('abc@xyz.financial')).toBe(true); + + }); + }); + +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco/js/install.loader.js b/src/Umbraco.Web.UI/Umbraco/js/install.loader.js index 66f00f742c..5415a106e1 100644 --- a/src/Umbraco.Web.UI/Umbraco/js/install.loader.js +++ b/src/Umbraco.Web.UI/Umbraco/js/install.loader.js @@ -7,10 +7,11 @@ LazyLoad.js( [ 'lib/angular/1.1.5/angular-mocks.js', 'lib/angular/1.1.5/angular-sanitize.min.js', 'lib/underscore/underscore-min.js', - 'js/umbraco.installer.js' + 'js/umbraco.installer.js', + 'js/umbraco.directives.js' ], function () { jQuery(document).ready(function () { - angular.bootstrap(document, ['ngSanitize', 'umbraco.install']); + angular.bootstrap(document, ['ngSanitize', 'umbraco.install', 'umbraco.directives.validation']); }); } ); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml index a7ef52979d..bef809a593 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml @@ -20,6 +20,7 @@ + Umbraco diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index a696ccf0b1..30320b278e 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -230,7 +230,6 @@ namespace Umbraco.Web.Editors ///
/// [FileUploadCleanupFilter] - [MembershipProviderValidationFilter] public MemberDisplay PostSave( [ModelBinder(typeof(MemberBinder))] MemberSave contentItem) diff --git a/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs b/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs deleted file mode 100644 index aa95af3531..0000000000 --- a/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Net; -using System.Web.Http; -using System.Web.Http.Controllers; -using System.Web.Http.Filters; -using System.Web.Security; -using Umbraco.Core; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.Editors -{ - /// - /// This validates the submitted data in regards to the current membership provider - /// - internal class MembershipProviderValidationFilterAttribute : ActionFilterAttribute - { - public override void OnActionExecuting(HttpActionContext actionContext) - { - base.OnActionExecuting(actionContext); - - //default provider! - var membershipProvider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - - var contentItem = (MemberSave) actionContext.ActionArguments["contentItem"]; - - var validEmail = ValidateUniqueEmail(contentItem, membershipProvider, actionContext); - if (validEmail == false) - { - actionContext.ModelState.AddPropertyError( - new ValidationResult("Email address is already in use", new[] {"value"}), - string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); - } - - var validLogin = ValidateUniqueLogin(contentItem, membershipProvider, actionContext); - if (validLogin == false) - { - actionContext.ModelState.AddPropertyError( - new ValidationResult("Username is already in use", new[] { "value" }), - string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); - } - } - - internal bool ValidateUniqueLogin(MemberSave contentItem, MembershipProvider membershipProvider, HttpActionContext actionContext) - { - if (contentItem == null) throw new ArgumentNullException("contentItem"); - if (membershipProvider == null) throw new ArgumentNullException("membershipProvider"); - - int totalRecs; - var existingByName = membershipProvider.FindUsersByName(contentItem.Username.Trim(), 0, int.MaxValue, out totalRecs); - switch (contentItem.Action) - { - case ContentSaveAction.Save: - - //ok, we're updating the member, we need to check if they are changing their login and if so, does it exist already ? - if (contentItem.PersistedContent.Username.InvariantEquals(contentItem.Username.Trim()) == false) - { - //they are changing their login name - if (existingByName.Cast().Select(x => x.UserName) - .Any(x => x == contentItem.Username.Trim())) - { - //the user cannot use this login - return false; - } - } - break; - case ContentSaveAction.SaveNew: - //check if the user's login already exists - if (existingByName.Cast().Select(x => x.UserName) - .Any(x => x == contentItem.Username.Trim())) - { - //the user cannot use this login - return false; - } - break; - default: - //we don't support this for members - throw new HttpResponseException(HttpStatusCode.NotFound); - } - - return true; - } - - internal bool ValidateUniqueEmail(MemberSave contentItem, MembershipProvider membershipProvider, HttpActionContext actionContext) - { - if (contentItem == null) throw new ArgumentNullException("contentItem"); - if (membershipProvider == null) throw new ArgumentNullException("membershipProvider"); - - if (membershipProvider.RequiresUniqueEmail == false) - { - return true; - } - - int totalRecs; - var existingByEmail = membershipProvider.FindUsersByEmail(contentItem.Email.Trim(), 0, int.MaxValue, out totalRecs); - switch (contentItem.Action) - { - case ContentSaveAction.Save: - //ok, we're updating the member, we need to check if they are changing their email and if so, does it exist already ? - if (contentItem.PersistedContent.Email.InvariantEquals(contentItem.Email.Trim()) == false) - { - //they are changing their email - if (existingByEmail.Cast().Select(x => x.Email) - .Any(x => x.InvariantEquals(contentItem.Email.Trim()))) - { - //the user cannot use this email - return false; - } - } - break; - case ContentSaveAction.SaveNew: - //check if the user's email already exists - if (existingByEmail.Cast().Select(x => x.Email) - .Any(x => x.InvariantEquals(contentItem.Email.Trim()))) - { - //the user cannot use this email - return false; - } - break; - default: - //we don't support this for members - throw new HttpResponseException(HttpStatusCode.NotFound); - } - - return true; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 6edb9d7960..f47c280d6d 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -145,18 +145,24 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache var eMgr = GetExamineManagerSafe(); if (eMgr != null) { - try - { - //by default use the InternalSearcher - return eMgr.SearchProviderCollection["InternalSearcher"]; - } - catch (FileNotFoundException) - { - //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! - } + try + { + //by default use the InternalSearcher + return eMgr.SearchProviderCollection["InternalSearcher"]; + } + catch (FileNotFoundException) + { + //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! + } + catch (NullReferenceException) + { + //This will occur when the search provider cannot be initialized. In newer examine versions the initialization is lazy and therefore + // the manager will return the singleton without throwing initialization errors, however if examine isn't configured correctly a null + // reference error will occur because the examine settings are null. + } } return null; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c8a4cc61e7..50b0bd0c55 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -401,7 +401,6 @@ - diff --git a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs index 3893167a73..49669fd427 100644 --- a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Net; +using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.ModelBinding; using System.Web.Security; @@ -12,6 +15,7 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.WebApi.Filters; using System.Linq; using Umbraco.Core.Models.Membership; +using Umbraco.Web; namespace Umbraco.Web.WebApi.Binders { @@ -194,6 +198,52 @@ namespace Umbraco.Web.WebApi.Binders /// internal class MemberValidationHelper : ContentItemValidationHelper { + /// + /// We need to manually validate a few things here like email and login to make sure they are valid and aren't duplicates + /// + /// + /// + /// + protected override bool ValidatePropertyData(ContentItemBasic postedItem, HttpActionContext actionContext) + { + var memberSave = (MemberSave)postedItem; + + if (memberSave.Username.IsNullOrWhiteSpace()) + { + actionContext.ModelState.AddPropertyError( + new ValidationResult("Invalid user name", new[] { "value" }), + string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + } + + if (memberSave.Email.IsNullOrWhiteSpace() || new EmailAddressAttribute().IsValid(memberSave.Email) == false) + { + actionContext.ModelState.AddPropertyError( + new ValidationResult("Invalid email", new[] { "value" }), + string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + } + + //default provider! + var membershipProvider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); + + var validEmail = ValidateUniqueEmail(memberSave, membershipProvider, actionContext); + if (validEmail == false) + { + actionContext.ModelState.AddPropertyError( + new ValidationResult("Email address is already in use", new[] { "value" }), + string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + } + + var validLogin = ValidateUniqueLogin(memberSave, membershipProvider, actionContext); + if (validLogin == false) + { + actionContext.ModelState.AddPropertyError( + new ValidationResult("Username is already in use", new[] { "value" }), + string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + } + + return base.ValidatePropertyData(postedItem, actionContext); + } + protected override bool ValidateProperties(ContentItemBasic postedItem, HttpActionContext actionContext) { var propertiesToValidate = postedItem.Properties.ToList(); @@ -206,6 +256,90 @@ namespace Umbraco.Web.WebApi.Binders return ValidateProperties(propertiesToValidate.ToArray(), postedItem.PersistedContent.Properties.ToArray(), actionContext); } + + internal bool ValidateUniqueLogin(MemberSave contentItem, MembershipProvider membershipProvider, HttpActionContext actionContext) + { + if (contentItem == null) throw new ArgumentNullException("contentItem"); + if (membershipProvider == null) throw new ArgumentNullException("membershipProvider"); + + int totalRecs; + var existingByName = membershipProvider.FindUsersByName(contentItem.Username.Trim(), 0, int.MaxValue, out totalRecs); + switch (contentItem.Action) + { + case ContentSaveAction.Save: + + //ok, we're updating the member, we need to check if they are changing their login and if so, does it exist already ? + if (contentItem.PersistedContent.Username.InvariantEquals(contentItem.Username.Trim()) == false) + { + //they are changing their login name + if (existingByName.Cast().Select(x => x.UserName) + .Any(x => x == contentItem.Username.Trim())) + { + //the user cannot use this login + return false; + } + } + break; + case ContentSaveAction.SaveNew: + //check if the user's login already exists + if (existingByName.Cast().Select(x => x.UserName) + .Any(x => x == contentItem.Username.Trim())) + { + //the user cannot use this login + return false; + } + break; + default: + //we don't support this for members + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return true; + } + + internal bool ValidateUniqueEmail(MemberSave contentItem, MembershipProvider membershipProvider, HttpActionContext actionContext) + { + if (contentItem == null) throw new ArgumentNullException("contentItem"); + if (membershipProvider == null) throw new ArgumentNullException("membershipProvider"); + + if (membershipProvider.RequiresUniqueEmail == false) + { + return true; + } + + int totalRecs; + var existingByEmail = membershipProvider.FindUsersByEmail(contentItem.Email.Trim(), 0, int.MaxValue, out totalRecs); + switch (contentItem.Action) + { + case ContentSaveAction.Save: + //ok, we're updating the member, we need to check if they are changing their email and if so, does it exist already ? + if (contentItem.PersistedContent.Email.InvariantEquals(contentItem.Email.Trim()) == false) + { + //they are changing their email + if (existingByEmail.Cast().Select(x => x.Email) + .Any(x => x.InvariantEquals(contentItem.Email.Trim()))) + { + //the user cannot use this email + return false; + } + } + break; + case ContentSaveAction.SaveNew: + //check if the user's email already exists + if (existingByEmail.Cast().Select(x => x.Email) + .Any(x => x.InvariantEquals(contentItem.Email.Trim()))) + { + //the user cannot use this email + return false; + } + break; + default: + //we don't support this for members + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return true; + } } } } \ No newline at end of file diff --git a/src/UmbracoExamine/BaseUmbracoIndexer.cs b/src/UmbracoExamine/BaseUmbracoIndexer.cs index aa0a5c0b63..48fcb85699 100644 --- a/src/UmbracoExamine/BaseUmbracoIndexer.cs +++ b/src/UmbracoExamine/BaseUmbracoIndexer.cs @@ -202,8 +202,9 @@ namespace UmbracoExamine //if temp local storage is configured use that, otherwise return the default if (_localTempStorageHelper.LuceneDirectory != null) { - return new IndexWriter(GetLuceneDirectory(), IndexingAnalyzer, - DeletePolicyTracker.Current.GetPolicy(IndexSetName), + var directory = GetLuceneDirectory(); + return new IndexWriter(directory, IndexingAnalyzer, + DeletePolicyTracker.Current.GetPolicy(directory), IndexWriter.MaxFieldLength.UNLIMITED); } diff --git a/src/UmbracoExamine/DeletePolicyTracker.cs b/src/UmbracoExamine/DeletePolicyTracker.cs index d002cc108d..3edcd12a24 100644 --- a/src/UmbracoExamine/DeletePolicyTracker.cs +++ b/src/UmbracoExamine/DeletePolicyTracker.cs @@ -14,9 +14,9 @@ namespace UmbracoExamine get { return Instance; } } - public IndexDeletionPolicy GetPolicy(string indexSetName) + public IndexDeletionPolicy GetPolicy(Lucene.Net.Store.Directory directory) { - var resolved = _directories.GetOrAdd(indexSetName, s => new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy())); + var resolved = _directories.GetOrAdd(directory.GetLockID(), s => new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy())); return resolved; } } diff --git a/src/UmbracoExamine/UmbracoExamineSearcher.cs b/src/UmbracoExamine/UmbracoExamineSearcher.cs index 437e5c5220..7d5c8b7776 100644 --- a/src/UmbracoExamine/UmbracoExamineSearcher.cs +++ b/src/UmbracoExamine/UmbracoExamineSearcher.cs @@ -170,9 +170,10 @@ namespace UmbracoExamine protected override IndexReader OpenNewReader() { + var directory = GetLuceneDirectory(); return IndexReader.Open( - GetLuceneDirectory(), - DeletePolicyTracker.Current.GetPolicy(IndexSetName), + directory, + DeletePolicyTracker.Current.GetPolicy(directory), true); } diff --git a/src/umbraco.businesslogic/ui.cs b/src/umbraco.businesslogic/ui.cs index e6bfbb2435..5f2579d9ec 100644 --- a/src/umbraco.businesslogic/ui.cs +++ b/src/umbraco.businesslogic/ui.cs @@ -38,6 +38,8 @@ namespace umbraco [Obsolete("Get the current culture/language from the currently logged in IUser, the IUser object is available on most Umbraco base classes and on the UmbracoContext")] public static string Culture(User u) { + if (ApplicationContext.Current == null) return string.Empty; + var found = UserExtensions.GetUserCulture(u.Language, ApplicationContext.Current.Services.TextService); return found == null ? string.Empty : found.Name; } @@ -46,6 +48,8 @@ namespace umbraco [Obsolete("Get the current culture/language from the currently logged in IUser, the IUser object is available on most Umbraco base classes and on the UmbracoContext")] internal static string Culture(IUser u) { + if (ApplicationContext.Current == null) return string.Empty; + var found = u.GetUserCulture(ApplicationContext.Current.Services.TextService); return found == null ? string.Empty : found.Name; } @@ -94,11 +98,15 @@ namespace umbraco /// public static string Text(string Key, User u) { + if (ApplicationContext.Current == null) return "[" + Key + "]"; + return ApplicationContext.Current.Services.TextService.Localize(Key, GetCultureFromUserLanguage(GetLanguage(u))); } internal static string Text(string key, IUser u) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize(key, GetCultureFromUserLanguage(GetLanguage(u))); } @@ -109,6 +117,8 @@ namespace umbraco /// public static string Text(string Key) { + if (ApplicationContext.Current == null) return "[" + Key + "]"; + return ApplicationContext.Current.Services.TextService.Localize(Key, GetCultureFromUserLanguage(GetLanguage())); } @@ -121,6 +131,8 @@ namespace umbraco /// public static string Text(string Area, string Key, User u) { + if (ApplicationContext.Current == null) return "[" + Key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", Area, Key), GetCultureFromUserLanguage(GetLanguage(u))); @@ -128,6 +140,8 @@ namespace umbraco public static string Text(string area, string key, IUser u) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage(u))); @@ -141,6 +155,8 @@ namespace umbraco /// public static string Text(string Area, string Key) { + if (ApplicationContext.Current == null) return "[" + Key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", Area, Key), GetCultureFromUserLanguage(GetLanguage())); @@ -156,6 +172,8 @@ namespace umbraco /// public static string Text(string Area, string Key, string[] Variables, User u) { + if (ApplicationContext.Current == null) return "[" + Key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", Area, Key), GetCultureFromUserLanguage(GetLanguage(u)), @@ -164,6 +182,8 @@ namespace umbraco internal static string Text(string area, string key, string[] variables) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage()), @@ -172,6 +192,8 @@ namespace umbraco internal static string Text(string area, string key, string[] variables, IUser u) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage(u)), @@ -188,6 +210,8 @@ namespace umbraco /// public static string Text(string Area, string Key, string Variable, User u) { + if (ApplicationContext.Current == null) return "[" + Key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", Area, Key), GetCultureFromUserLanguage(GetLanguage(u)), @@ -196,6 +220,8 @@ namespace umbraco internal static string Text(string area, string key, string variable) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage()), @@ -204,6 +230,8 @@ namespace umbraco internal static string Text(string area, string key, string variable, IUser u) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage(u)), @@ -228,6 +256,8 @@ namespace umbraco /// public static string GetText(string area, string key) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage())); @@ -242,6 +272,8 @@ namespace umbraco /// public static string GetText(string area, string key, string[] variables) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage()), @@ -257,6 +289,8 @@ namespace umbraco /// public static string GetText(string area, string key, string variable) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage()), @@ -274,6 +308,8 @@ namespace umbraco /// This is the underlying call for all Text/GetText method calls public static string GetText(string area, string key, string[] variables, string language) { + if (ApplicationContext.Current == null) return "[" + key + "]"; + return ApplicationContext.Current.Services.TextService.Localize( string.Format("{0}/{1}", area, key), GetCultureFromUserLanguage(GetLanguage()),