diff --git a/.gitignore b/.gitignore index 9496a86e70..51405dd753 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,6 @@ build/_BuildOutput/ tools/NDepend/ src/*.vspx src/*.psess +NDependOut/* +*.ndproj +QueryResult.htm diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs index ae01532c87..2ef594c8c2 100644 --- a/src/Umbraco.Core/Models/PropertyExtensions.cs +++ b/src/Umbraco.Core/Models/PropertyExtensions.cs @@ -43,7 +43,7 @@ namespace Umbraco.Core.Models //This seems to fail during testing //SD: With the new null checks below, this shouldn't fail anymore. var dt = property.PropertyType.DataType(property.Id, dataTypeService); - if (dt != null && dt.Data != null) + if (dt != null && dt.Data != null && dt.Data.Value != null) { //We've already got the value for the property so we're going to give it to the // data type's data property so it doesn't go re-look up the value from the db again. diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index b50102396a..a2963343e3 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -146,7 +146,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void CreateUmbracoUserTypeData() { - _database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 1, Alias = "admin", Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F" }); + _database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 1, Alias = "admin", Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F7" }); _database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 2, Alias = "writer", Name = "Writer", DefaultPermissions = "CAH:F" }); _database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 3, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5F" }); _database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 4, Alias = "translator", Name = "Translator", DefaultPermissions = "AF" }); diff --git a/src/Umbraco.Core/PublishedContentHelper.cs b/src/Umbraco.Core/PublishedContentHelper.cs index 1e7fc1ef18..86513ede02 100644 --- a/src/Umbraco.Core/PublishedContentHelper.cs +++ b/src/Umbraco.Core/PublishedContentHelper.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Xml.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Dynamics; +using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -35,7 +36,7 @@ namespace Umbraco.Core /// internal static Func GetDataTypeCallback = null; - private static readonly ConcurrentDictionary, Guid> PropertyTypeCache = new ConcurrentDictionary, Guid>(); + private static readonly ConcurrentDictionary, Guid> PropertyTypeCache = new ConcurrentDictionary, Guid>(); /// /// Return the GUID Id for the data type assigned to the document type with the property alias @@ -43,16 +44,29 @@ namespace Umbraco.Core /// /// /// + /// /// - internal static Guid GetDataType(ApplicationContext applicationContext, string docTypeAlias, string propertyAlias) + internal static Guid GetDataType(ApplicationContext applicationContext, string docTypeAlias, string propertyAlias, PublishedItemType itemType) { if (GetDataTypeCallback != null) return GetDataTypeCallback(docTypeAlias, propertyAlias); - var key = new Tuple(docTypeAlias, propertyAlias); + var key = new Tuple(docTypeAlias, propertyAlias, itemType); return PropertyTypeCache.GetOrAdd(key, tuple => { - var result = applicationContext.Services.ContentTypeService.GetContentType(docTypeAlias); + IContentTypeComposition result = null; + switch (itemType) + { + case PublishedItemType.Content: + result = applicationContext.Services.ContentTypeService.GetContentType(docTypeAlias); + break; + case PublishedItemType.Media: + result = applicationContext.Services.ContentTypeService.GetMediaType(docTypeAlias); + break; + default: + throw new ArgumentOutOfRangeException("itemType"); + } + if (result == null) return Guid.Empty; //SD: we need to check for 'any' here because the collection is backed by KeyValuePair which is a struct diff --git a/src/Umbraco.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs index 3cbe21991b..36a5deff75 100644 --- a/src/Umbraco.Core/TypeFinder.cs +++ b/src/Umbraco.Core/TypeFinder.cs @@ -19,54 +19,56 @@ using Umbraco.Core.IO; namespace Umbraco.Core { - /// - /// A utility class to find all classes of a certain type by reflection in the current bin folder - /// of the web application. - /// - public static class TypeFinder - { - - private static readonly ConcurrentBag LocalFilteredAssemblyCache = new ConcurrentBag(); - private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim(); - private static ReadOnlyCollection _allAssemblies = null; - private static ReadOnlyCollection _binFolderAssemblies = null; - private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); + /// + /// A utility class to find all classes of a certain type by reflection in the current bin folder + /// of the web application. + /// + public static class TypeFinder + { + private static readonly HashSet LocalFilteredAssemblyCache = new HashSet(); + private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim(); + private static HashSet _allAssemblies = null; + private static HashSet _binFolderAssemblies = null; + private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); - /// - /// lazily load a reference to all assemblies and only local assemblies. - /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder - /// - /// - /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been - /// loaded in the CLR, not all assemblies. - /// See these threads: - /// http://issues.umbraco.org/issue/U5-198 - /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app - /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl - /// - internal static IEnumerable GetAllAssemblies() - { - if (_allAssemblies == null) - { - using (new WriteLock(Locker)) - { - List assemblies = null; - try - { - var isHosted = HttpContext.Current != null; + /// + /// lazily load a reference to all assemblies and only local assemblies. + /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder + /// + /// + /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been + /// loaded in the CLR, not all assemblies. + /// See these threads: + /// http://issues.umbraco.org/issue/U5-198 + /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app + /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl + /// + internal static HashSet GetAllAssemblies() + { + using (var lck = new UpgradeableReadLock(Locker)) + { + if (_allAssemblies == null) + { - try - { - if (isHosted) - { - assemblies = new List(BuildManager.GetReferencedAssemblies().Cast()); - } - } - catch (InvalidOperationException e) - { - if (!(e.InnerException is SecurityException)) - throw; - } + lck.UpgradeToWriteLock(); + + HashSet assemblies = null; + try + { + var isHosted = HttpContext.Current != null; + + try + { + if (isHosted) + { + assemblies = new HashSet(BuildManager.GetReferencedAssemblies().Cast()); + } + } + catch (InvalidOperationException e) + { + if (!(e.InnerException is SecurityException)) + throw; + } if (assemblies == null) @@ -77,7 +79,7 @@ namespace Umbraco.Core var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList(); //var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; //var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); - assemblies = new List(); + assemblies = new HashSet(); foreach (var a in binAssemblyFiles) { try @@ -99,151 +101,161 @@ namespace Umbraco.Core } } } - + //if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies. - if (!assemblies.Any()) - { - assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList()); - } + if (!assemblies.Any()) + { + foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) + { + assemblies.Add(a); + } + } - //here we are trying to get the App_Code assembly - var fileExtensions = new[] {".cs", ".vb"}; //only vb and cs files are supported - var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code"))); - //check if the folder exists and if there are any files in it with the supported file extensions - if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))) - { - var appCodeAssembly = Assembly.Load("App_Code"); - if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already - assemblies.Add(appCodeAssembly); - } + //here we are trying to get the App_Code assembly + var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported + var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code"))); + //check if the folder exists and if there are any files in it with the supported file extensions + if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))) + { + var appCodeAssembly = Assembly.Load("App_Code"); + if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already + assemblies.Add(appCodeAssembly); + } - //now set the _allAssemblies - _allAssemblies = new ReadOnlyCollection(assemblies); + //now set the _allAssemblies + _allAssemblies = new HashSet(assemblies); - } - catch (InvalidOperationException e) - { - if (!(e.InnerException is SecurityException)) - throw; + } + catch (InvalidOperationException e) + { + if (!(e.InnerException is SecurityException)) + throw; - _binFolderAssemblies = _allAssemblies; - } - } - } + _binFolderAssemblies = _allAssemblies; + } + } - return _allAssemblies; - } - - /// - /// Returns only assemblies found in the bin folder that have been loaded into the app domain. - /// - /// - /// - /// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used. - /// - internal static IEnumerable GetBinAssemblies() - { + return _allAssemblies; + } + } - if (_binFolderAssemblies == null) - { - using (new WriteLock(Locker)) - { - var assemblies = GetAssembliesWithKnownExclusions().ToArray(); - var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; - var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); - var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName); - var safeDomainAssemblies = new List(); - var binFolderAssemblies = new List(); + /// + /// Returns only assemblies found in the bin folder that have been loaded into the app domain. + /// + /// + /// + /// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used. + /// + internal static HashSet GetBinAssemblies() + { - foreach (var a in assemblies) - { - try - { - //do a test to see if its queryable in med trust - var assemblyFile = a.GetAssemblyFile(); - safeDomainAssemblies.Add(a); - } - catch (SecurityException) - { - //we will just ignore this because this will fail - //in medium trust for system assemblies, we get an exception but we just want to continue until we get to - //an assembly that is ok. - } - } + if (_binFolderAssemblies == null) + { + using (new WriteLock(Locker)) + { + var assemblies = GetAssembliesWithKnownExclusions().ToArray(); + var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; + var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); + var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName); + var safeDomainAssemblies = new HashSet(); + var binFolderAssemblies = new HashSet(); - foreach (var assemblyName in domainAssemblyNames) - { - try - { - var foundAssembly = - safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile()); - if (foundAssembly != null) - { - binFolderAssemblies.Add(foundAssembly); - } - } - catch (SecurityException) - { - //we will just ignore this because if we are trying to do a call to: - // AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName))) - //in medium trust for system assemblies, we get an exception but we just want to continue until we get to - //an assembly that is ok. - } - } + foreach (var a in assemblies) + { + try + { + //do a test to see if its queryable in med trust + var assemblyFile = a.GetAssemblyFile(); + safeDomainAssemblies.Add(a); + } + catch (SecurityException) + { + //we will just ignore this because this will fail + //in medium trust for system assemblies, we get an exception but we just want to continue until we get to + //an assembly that is ok. + } + } - _binFolderAssemblies = new ReadOnlyCollection(binFolderAssemblies); - } - } - return _binFolderAssemblies; - } + foreach (var assemblyName in domainAssemblyNames) + { + try + { + var foundAssembly = + safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile()); + if (foundAssembly != null) + { + binFolderAssemblies.Add(foundAssembly); + } + } + catch (SecurityException) + { + //we will just ignore this because if we are trying to do a call to: + // AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName))) + //in medium trust for system assemblies, we get an exception but we just want to continue until we get to + //an assembly that is ok. + } + } - /// - /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan - /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are - /// cached for perforance reasons. - /// - /// - /// - internal static IEnumerable GetAssembliesWithKnownExclusions( - IEnumerable excludeFromResults = null) - { - if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache; - using (new WriteLock(LocalFilteredAssemblyCacheLocker)) - { - var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter); - assemblies.ForEach(LocalFilteredAssemblyCache.Add); - } - return LocalFilteredAssemblyCache; - } + _binFolderAssemblies = new HashSet(binFolderAssemblies); + } + } + return _binFolderAssemblies; + } - /// - /// Return a list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter - /// - /// - /// - /// - private static IEnumerable GetFilteredAssemblies( - IEnumerable excludeFromResults = null, - string[] exclusionFilter = null) - { - if (excludeFromResults == null) - excludeFromResults = new List(); - if (exclusionFilter == null) - exclusionFilter = new string[] { }; + /// + /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan + /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are + /// cached for perforance reasons. + /// + /// + /// + internal static HashSet GetAssembliesWithKnownExclusions( + IEnumerable excludeFromResults = null) + { + using (var lck = new UpgradeableReadLock(LocalFilteredAssemblyCacheLocker)) + { + if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache; - return GetAllAssemblies() - .Where(x => !excludeFromResults.Contains(x) - && !x.GlobalAssemblyCache - && !exclusionFilter.Any(f => x.FullName.StartsWith(f))); - } + lck.UpgradeToWriteLock(); - /// - /// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins - /// - /// - /// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match - /// - internal static readonly string[] KnownAssemblyExclusionFilter = new[] + var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter); + foreach (var a in assemblies) + { + LocalFilteredAssemblyCache.Add(a); + } + + return LocalFilteredAssemblyCache; + } + } + + /// + /// Return a distinct list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter + /// + /// + /// + /// + private static IEnumerable GetFilteredAssemblies( + IEnumerable excludeFromResults = null, + string[] exclusionFilter = null) + { + if (excludeFromResults == null) + excludeFromResults = new HashSet(); + if (exclusionFilter == null) + exclusionFilter = new string[] { }; + + return GetAllAssemblies() + .Where(x => !excludeFromResults.Contains(x) + && !x.GlobalAssemblyCache + && !exclusionFilter.Any(f => x.FullName.StartsWith(f))); + } + + /// + /// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins + /// + /// + /// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match + /// + internal static readonly string[] KnownAssemblyExclusionFilter = new[] { "mscorlib,", "System.", @@ -287,11 +299,11 @@ namespace Umbraco.Core /// /// /// - public static IEnumerable FindClassesOfTypeWithAttribute() - where TAttribute : Attribute - { - return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true); - } + public static IEnumerable FindClassesOfTypeWithAttribute() + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true); + } /// /// Finds any classes derived from the type T that contain the attribute TAttribute @@ -300,11 +312,11 @@ namespace Umbraco.Core /// /// /// - public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies) - where TAttribute : Attribute - { - return FindClassesOfTypeWithAttribute(assemblies, true); - } + public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies) + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(assemblies, true); + } /// /// Finds any classes derived from the type T that contain the attribute TAttribute @@ -314,13 +326,13 @@ namespace Umbraco.Core /// /// /// - public static IEnumerable FindClassesOfTypeWithAttribute( - IEnumerable assemblies, - bool onlyConcreteClasses) - where TAttribute : Attribute - { - return FindClassesOfTypeWithAttribute(typeof (T), assemblies, onlyConcreteClasses); - } + public static IEnumerable FindClassesOfTypeWithAttribute( + IEnumerable assemblies, + bool onlyConcreteClasses) + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(typeof(T), assemblies, onlyConcreteClasses); + } /// /// Finds any classes derived from the assignTypeFrom Type that contain the attribute TAttribute @@ -330,85 +342,85 @@ namespace Umbraco.Core /// /// /// - public static IEnumerable FindClassesOfTypeWithAttribute( - Type assignTypeFrom, - IEnumerable assemblies, + public static IEnumerable FindClassesOfTypeWithAttribute( + Type assignTypeFrom, + IEnumerable assemblies, bool onlyConcreteClasses) where TAttribute : Attribute - { - if (assemblies == null) throw new ArgumentNullException("assemblies"); - - return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses, + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); + + return GetClasses(assignTypeFrom, assemblies, onlyConcreteClasses, //the additional filter will ensure that any found types also have the attribute applied. - t => t.GetCustomAttributes(false).Any()); - } + t => t.GetCustomAttributes(false).Any()); + } - /// - /// Searches all filtered local assemblies specified for classes of the type passed in. - /// - /// - /// - public static IEnumerable FindClassesOfType() - { - return FindClassesOfType(GetAssembliesWithKnownExclusions(), true); - } + /// + /// Searches all filtered local assemblies specified for classes of the type passed in. + /// + /// + /// + public static IEnumerable FindClassesOfType() + { + return FindClassesOfType(GetAssembliesWithKnownExclusions(), true); + } - /// - /// Returns all types found of in the assemblies specified of type T - /// - /// - /// - /// - /// - public static IEnumerable FindClassesOfType(IEnumerable assemblies, bool onlyConcreteClasses) - { - if (assemblies == null) throw new ArgumentNullException("assemblies"); + /// + /// Returns all types found of in the assemblies specified of type T + /// + /// + /// + /// + /// + public static IEnumerable FindClassesOfType(IEnumerable assemblies, bool onlyConcreteClasses) + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); return GetClasses(typeof(T), assemblies, onlyConcreteClasses); - } + } - /// - /// Returns all types found of in the assemblies specified of type T - /// - /// - /// - /// - public static IEnumerable FindClassesOfType(IEnumerable assemblies) - { - return FindClassesOfType(assemblies, true); - } + /// + /// Returns all types found of in the assemblies specified of type T + /// + /// + /// + /// + public static IEnumerable FindClassesOfType(IEnumerable assemblies) + { + return FindClassesOfType(assemblies, true); + } - /// - /// Finds the classes with attribute. - /// - /// - /// The assemblies. - /// if set to true only concrete classes. - /// - public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) - where T : Attribute - { - return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses); - } + /// + /// Finds the classes with attribute. + /// + /// + /// The assemblies. + /// if set to true only concrete classes. + /// + public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) + where T : Attribute + { + return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses); + } - /// - /// Finds any classes with the attribute. - /// - /// The attribute type - /// The assemblies. - /// if set to true only concrete classes. - /// - public static IEnumerable FindClassesWithAttribute( - Type attributeType, - IEnumerable assemblies, - bool onlyConcreteClasses) - { - if (assemblies == null) throw new ArgumentNullException("assemblies"); + /// + /// Finds any classes with the attribute. + /// + /// The attribute type + /// The assemblies. + /// if set to true only concrete classes. + /// + public static IEnumerable FindClassesWithAttribute( + Type attributeType, + IEnumerable assemblies, + bool onlyConcreteClasses) + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); - if (TypeHelper.IsTypeAssignableFrom(attributeType) == false) - throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type"); + if (TypeHelper.IsTypeAssignableFrom(attributeType) == false) + throw new ArgumentException("The type specified: " + attributeType + " is not an Attribute type"); - var foundAssignableTypes = new List(); + var foundAssignableTypes = new HashSet(); var assemblyList = assemblies.ToArray(); @@ -418,71 +430,74 @@ namespace Umbraco.Core var referencedAssemblies = TypeHelper.GetReferencedAssemblies(attributeType, assemblyList); foreach (var a in referencedAssemblies) - { + { //get all types in the assembly that are sub types of the current type var allTypes = GetTypesWithFormattedException(a).ToArray(); - - var types = allTypes.Where(t => TypeHelper.IsNonStaticClass(t) - && (onlyConcreteClasses == false || t.IsAbstract == false) - //the type must have this attribute + + var types = allTypes.Where(t => TypeHelper.IsNonStaticClass(t) + && (onlyConcreteClasses == false || t.IsAbstract == false) + //the type must have this attribute && t.GetCustomAttributes(attributeType, false).Any()); - foundAssignableTypes.AddRange(types); - } + foreach (var t in types) + { + foundAssignableTypes.Add(t); + } + } - return foundAssignableTypes; - } + return foundAssignableTypes; + } - /// - /// Finds the classes with attribute. - /// - /// - /// The assemblies. - /// - public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies) - where T : Attribute - { - return FindClassesWithAttribute(assemblies, true); - } + /// + /// Finds the classes with attribute. + /// + /// + /// The assemblies. + /// + public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies) + where T : Attribute + { + return FindClassesWithAttribute(assemblies, true); + } - /// - /// Finds the classes with attribute in filtered local assemblies - /// - /// - /// - public static IEnumerable FindClassesWithAttribute() - where T : Attribute - { - return FindClassesWithAttribute(GetAssembliesWithKnownExclusions()); - } + /// + /// Finds the classes with attribute in filtered local assemblies + /// + /// + /// + public static IEnumerable FindClassesWithAttribute() + where T : Attribute + { + return FindClassesWithAttribute(GetAssembliesWithKnownExclusions()); + } - #region Private methods - - /// - /// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly - /// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type - /// deriving from the base type. - /// - /// - /// - /// - /// An additional filter to apply for what types will actually be included in the return value - /// - private static IEnumerable GetClasses( - Type assignTypeFrom, - IEnumerable assemblies, + #region Private methods + + /// + /// Finds types that are assignable from the assignTypeFrom parameter and will scan for these types in the assembly + /// list passed in, however we will only scan assemblies that have a reference to the assignTypeFrom Type or any type + /// deriving from the base type. + /// + /// + /// + /// + /// An additional filter to apply for what types will actually be included in the return value + /// + private static IEnumerable GetClasses( + Type assignTypeFrom, + IEnumerable assemblies, bool onlyConcreteClasses, Func additionalFilter = null) - { + { //the default filter will always return true. if (additionalFilter == null) { additionalFilter = type => true; } - var foundAssignableTypes = new List(); + var foundAssignableTypes = new HashSet(); var assemblyList = assemblies.ToArray(); @@ -510,8 +525,11 @@ namespace Umbraco.Core .ToArray(); //add the types to our list to return - foundAssignableTypes.AddRange(filteredTypes); - + foreach (var t in filteredTypes) + { + foundAssignableTypes.Add(t); + } + //now we need to include types that may be inheriting from sub classes of the type being searched for //so we will search in assemblies that reference those types too. foreach (var subTypesInAssembly in allSubTypes.GroupBy(x => x.Assembly)) @@ -529,54 +547,61 @@ namespace Umbraco.Core //if there's a base class amongst the types then we'll only search for that type. //otherwise we'll have to search for all of them. - var subTypesToSearch = new List(); + var subTypesToSearch = new HashSet(); if (baseClassAttempt.Success) { subTypesToSearch.Add(baseClassAttempt.Result); } else { - subTypesToSearch.AddRange(subTypeList); + foreach (var t in subTypeList) + { + subTypesToSearch.Add(t); + } } - + foreach (var typeToSearch in subTypesToSearch) { //recursively find the types inheriting from this sub type in the other non-scanned assemblies. var foundTypes = GetClasses(typeToSearch, otherAssemblies, onlyConcreteClasses, additionalFilter); - foundAssignableTypes.AddRange(foundTypes); + + foreach (var f in foundTypes) + { + foundAssignableTypes.Add(f); + } } - + } - } - return foundAssignableTypes; - } + } + return foundAssignableTypes; + } - private static IEnumerable GetTypesWithFormattedException(Assembly a) - { - //if the assembly is dynamic, do not try to scan it - if (a.IsDynamic) - return Enumerable.Empty(); + private static IEnumerable GetTypesWithFormattedException(Assembly a) + { + //if the assembly is dynamic, do not try to scan it + if (a.IsDynamic) + return Enumerable.Empty(); - try - { - return a.GetExportedTypes(); - } - catch (ReflectionTypeLoadException ex) - { - var sb = new StringBuilder(); - sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:"); - foreach (var loaderException in ex.LoaderExceptions.WhereNotNull()) - { - sb.AppendLine("Exception: " + loaderException); - } - throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString()); - } - } + try + { + return a.GetExportedTypes(); + } + catch (ReflectionTypeLoadException ex) + { + var sb = new StringBuilder(); + sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:"); + foreach (var loaderException in ex.LoaderExceptions.WhereNotNull()) + { + sb.AppendLine("Exception: " + loaderException); + } + throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString()); + } + } - #endregion + #endregion - - } + + } } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 2086b9b5d0..efa50075bf 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; +using System.Web; using System.Xml.Linq; using System.Xml.XPath; using Examine; @@ -16,6 +17,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.UmbracoExamine; using Umbraco.Web; using Umbraco.Web.PublishedCache; @@ -68,6 +70,38 @@ namespace Umbraco.Tests.PublishedContent return GetNode(id, GetUmbracoContext("/test", 1234)); } + [Test] + public void Get_Property_Value_Uses_Converter() + { + var mType = MockedContentTypes.CreateImageMediaType(); + //lets add an RTE to this + mType.PropertyGroups.First().PropertyTypes.Add( + new PropertyType(new Guid(), DataTypeDatabaseType.Nvarchar) + { + Alias = "content", + Name = "Rich Text", + DataTypeDefinitionId = -87 //tiny mce + }); + ServiceContext.ContentTypeService.Save(mType); + var media = MockedMedia.CreateMediaImage(mType, -1); + media.Properties["content"].Value = "
This is some content
"; + ServiceContext.MediaService.Save(media); + + var publishedMedia = GetNode(media.Id); + + var propVal = publishedMedia.GetPropertyValue("content"); + Assert.IsTrue(TypeHelper.IsTypeAssignableFrom(propVal.GetType())); + Assert.AreEqual("
This is some content
", propVal.ToString()); + + var propVal2 = publishedMedia.GetPropertyValue("content"); + Assert.IsTrue(TypeHelper.IsTypeAssignableFrom(propVal2.GetType())); + Assert.AreEqual("
This is some content
", propVal2.ToString()); + + var propVal3 = publishedMedia.GetPropertyValue("Content"); + Assert.IsTrue(TypeHelper.IsTypeAssignableFrom(propVal3.GetType())); + Assert.AreEqual("
This is some content
", propVal3.ToString()); + } + [Test] public void Ensure_Children_Sorted_With_Examine() { @@ -339,7 +373,6 @@ namespace Umbraco.Tests.PublishedContent Assert.AreEqual(mChild1.Id, publishedSubChild1.Parent.Id); } - [Test] public void Ancestors_Without_Examine() { diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 3a7efed60c..c39964e6da 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -2138,6 +2138,7 @@ + diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/EditProfile.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/EditProfile.cshtml new file mode 100644 index 0000000000..27457c2f7e --- /dev/null +++ b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/EditProfile.cshtml @@ -0,0 +1,52 @@ +@inherits Umbraco.Web.Macros.PartialViewMacroPage + +@using System.Web.Mvc.Html +@using ClientDependency.Core.Mvc +@using umbraco.cms.businesslogic.member +@using Umbraco.Web +@using Umbraco.Web.Models +@using Umbraco.Web.Controllers + +@{ + var profileModel = new ProfileModel(); + + Html.EnableClientValidation(); + Html.EnableUnobtrusiveJavaScript(); + Html.RequiresJs("/umbraco_client/ui/jquery.js"); + Html.RequiresJs("/umbraco_client/Application/JQuery/jquery.validate.min.js"); + Html.RequiresJs("/umbraco_client/Application/JQuery/jquery.validate.unobtrusive.min.js"); +} + +@if (Member.IsLoggedOn()) +{ + @Html.RenderJsHere() + + using (Html.BeginUmbracoForm("HandleUpdateProfile")) + { +
+ Edit profile + + @Html.LabelFor(m => profileModel.Name) + @Html.TextBoxFor(m => profileModel.Name) + @Html.ValidationMessageFor(m => profileModel.Name) +
+ + @Html.LabelFor(m => profileModel.Email) + @Html.TextBoxFor(m => profileModel.Email) + @Html.ValidationMessageFor(m => profileModel.Email) +
+ + @for (var i = 0; i < profileModel.MemberProperties.Count; i++) + { + @Html.LabelFor(m => profileModel.MemberProperties[i].Value, profileModel.MemberProperties[i].Name) + @Html.EditorFor(m => profileModel.MemberProperties[i].Value) + @Html.HiddenFor(m => profileModel.MemberProperties[i].Alias) +
+ } + + @Html.HiddenFor(m => profileModel.MemberTypeAlias) + + +
+ } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Login.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Login.cshtml index 62b9632ad5..5eb4529001 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Login.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Login.cshtml @@ -2,6 +2,7 @@ @using System.Web.Mvc.Html @using ClientDependency.Core.Mvc +@using Umbraco.Web @using Umbraco.Web.Models @using Umbraco.Web.Controllers diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/LoginStatus.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/LoginStatus.cshtml index 72d63e2857..d889c67391 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/LoginStatus.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/LoginStatus.cshtml @@ -1,5 +1,6 @@ @inherits Umbraco.Web.Macros.PartialViewMacroPage @using ClientDependency.Core.Mvc +@using Umbraco.Web @using Umbraco.Web.Models @using Umbraco.Web.Controllers diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/RegisterMember.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/RegisterMember.cshtml index 2c94c04acc..6574c56690 100644 --- a/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/RegisterMember.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/RegisterMember.cshtml @@ -2,13 +2,13 @@ @using System.Web.Mvc.Html @using ClientDependency.Core.Mvc +@using Umbraco.Web @using Umbraco.Web.Models @using Umbraco.Web.Controllers @{ var registerModel = new RegisterModel(); - registerModel.FillModel(registerModel, Model.MacroParameters); - + Html.EnableClientValidation(); Html.EnableUnobtrusiveJavaScript(); Html.RequiresJs("/umbraco_client/ui/jquery.js"); @@ -23,6 +23,11 @@
Register Member + @Html.LabelFor(m => registerModel.Name) + @Html.TextBoxFor(m => registerModel.Name) + @Html.ValidationMessageFor(m => registerModel.Name) +
+ @Html.LabelFor(m => registerModel.Email) @Html.TextBoxFor(m => registerModel.Email) @Html.ValidationMessageFor(m => registerModel.Email) @@ -33,14 +38,16 @@ @Html.ValidationMessageFor(m => registerModel.Password)
- @for (var i = 0; i < registerModel.MemberProperties.Count; i++) - { - @Html.LabelFor(m => registerModel.MemberProperties[i].Value, registerModel.MemberProperties[i].Name) - @Html.EditorFor(m => registerModel.MemberProperties[i].Value) - @Html.HiddenFor(m => registerModel.MemberProperties[i].Alias) -
+ @if (registerModel.MemberProperties != null) { + for (var i = 0; i < registerModel.MemberProperties.Count; i++) + { + @Html.LabelFor(m => registerModel.MemberProperties[i].Value, registerModel.MemberProperties[i].Name) + @Html.EditorFor(m => registerModel.MemberProperties[i].Value) + @Html.HiddenFor(m => registerModel.MemberProperties[i].Alias) +
+ } } - + @Html.HiddenFor(m => registerModel.MemberTypeAlias) diff --git a/src/Umbraco.Web.UI/config/404handlers.Release.config b/src/Umbraco.Web.UI/config/404handlers.Release.config index 11bdbaf8ef..770f7ca64b 100644 --- a/src/Umbraco.Web.UI/config/404handlers.Release.config +++ b/src/Umbraco.Web.UI/config/404handlers.Release.config @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/404handlers.config b/src/Umbraco.Web.UI/config/404handlers.config index 69bf6f1dd0..b6dd88fa8b 100644 --- a/src/Umbraco.Web.UI/config/404handlers.config +++ b/src/Umbraco.Web.UI/config/404handlers.config @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/ClientDependency.config b/src/Umbraco.Web.UI/config/ClientDependency.config index a95c67b06d..3b80c0d7dd 100644 --- a/src/Umbraco.Web.UI/config/ClientDependency.config +++ b/src/Umbraco.Web.UI/config/ClientDependency.config @@ -10,7 +10,7 @@ NOTES: * Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config * A new version will invalidate both client and server cache and create new persisted files --> - +