diff --git a/src/Umbraco.Core/ActionsResolver.cs b/src/Umbraco.Core/ActionsResolver.cs index cae5a4575f..083704d3bd 100644 --- a/src/Umbraco.Core/ActionsResolver.cs +++ b/src/Umbraco.Core/ActionsResolver.cs @@ -9,14 +9,14 @@ namespace Umbraco.Core /// /// A resolver to return all IAction objects /// - internal sealed class ActionsResolver : ManyObjectsResolverBase + internal sealed class ActionsResolver : LazyManyObjectsResolverBase { /// /// Constructor /// /// - internal ActionsResolver(IEnumerable packageActions) + internal ActionsResolver(Func> packageActions) : base(packageActions) { @@ -34,9 +34,9 @@ namespace Umbraco.Core } protected override IEnumerable CreateInstances() - { + { var actions = new List(); - var foundIActions = PluginManager.Current.ResolveActions(); + var foundIActions = InstanceTypes; foreach (var type in foundIActions) { IAction typeInstance; diff --git a/src/Umbraco.Core/CacheRefreshersResolver.cs b/src/Umbraco.Core/CacheRefreshersResolver.cs index 31ed877e97..51c6cfc183 100644 --- a/src/Umbraco.Core/CacheRefreshersResolver.cs +++ b/src/Umbraco.Core/CacheRefreshersResolver.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core /// Constructor /// /// - internal CacheRefreshersResolver(IEnumerable refreshers) + internal CacheRefreshersResolver(Func> refreshers) : base(refreshers) { diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index eda2cf494c..228b1ed9d0 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -118,19 +118,19 @@ namespace Umbraco.Core new RepositoryFactory()); CacheRefreshersResolver.Current = new CacheRefreshersResolver( - PluginManager.Current.ResolveCacheRefreshers()); + () => PluginManager.Current.ResolveCacheRefreshers()); DataTypesResolver.Current = new DataTypesResolver( - PluginManager.Current.ResolveDataTypes()); + () => PluginManager.Current.ResolveDataTypes()); MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver( - PluginManager.Current.ResolveMacroRenderings()); + () => PluginManager.Current.ResolveMacroRenderings()); PackageActionsResolver.Current = new PackageActionsResolver( - PluginManager.Current.ResolvePackageActions()); + () => PluginManager.Current.ResolvePackageActions()); ActionsResolver.Current = new ActionsResolver( - PluginManager.Current.ResolveActions()); + () => PluginManager.Current.ResolveActions()); MacroPropertyTypeResolver.Current = new MacroPropertyTypeResolver( PluginManager.Current.ResolveMacroPropertyTypes()); diff --git a/src/Umbraco.Core/DataTypesResolver.cs b/src/Umbraco.Core/DataTypesResolver.cs index c9eba4f074..65dced66b3 100644 --- a/src/Umbraco.Core/DataTypesResolver.cs +++ b/src/Umbraco.Core/DataTypesResolver.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core /// Constructor /// /// - internal DataTypesResolver(IEnumerable dataTypes) + internal DataTypesResolver(Func> dataTypes) : base(dataTypes) { diff --git a/src/Umbraco.Core/Dictionary/CultureDictionaryFactoryResolver.cs b/src/Umbraco.Core/Dictionary/CultureDictionaryFactoryResolver.cs index 1d754e1970..2dd7881e08 100644 --- a/src/Umbraco.Core/Dictionary/CultureDictionaryFactoryResolver.cs +++ b/src/Umbraco.Core/Dictionary/CultureDictionaryFactoryResolver.cs @@ -5,7 +5,7 @@ namespace Umbraco.Core.Dictionary /// /// Resolves the current CultureDictionaryFactory /// - internal class CultureDictionaryFactoryResolver : SingleObjectResolverBase + internal sealed class CultureDictionaryFactoryResolver : SingleObjectResolverBase { internal CultureDictionaryFactoryResolver(ICultureDictionaryFactory factory) : base(factory) diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index f380c348f2..90a8e517a4 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -311,6 +311,7 @@ namespace Umbraco.Core.Models } /// + /// Gets the for the Creator of this content item. /// public static IProfile GetCreatorProfile(this IContentBase content) { @@ -353,7 +354,6 @@ namespace Umbraco.Core.Models /// Xml representation of the passed in public static XElement ToXml(this IContent content) { - //nodeName should match Casing.SafeAliasWithForcingCheck(content.ContentType.Alias); var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : content.ContentType.Alias.ToSafeAliasWithForcingCheck(); @@ -427,7 +427,8 @@ namespace Umbraco.Core.Models xml.Add(property.ToXml()); //Check for umbracoUrlName convention - if (property.Alias == "umbracoUrlName" && property.Value.ToString().Trim() != string.Empty) + if (property.Alias == "umbracoUrlName" && property.Value != null && + property.Value.ToString().Trim() != string.Empty) xml.SetAttributeValue("urlName", property.Value); } diff --git a/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs b/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs new file mode 100644 index 0000000000..21374a48f5 --- /dev/null +++ b/src/Umbraco.Core/ObjectResolution/LazyManyObjectsResolverbase.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Web; + +namespace Umbraco.Core.ObjectResolution +{ + /// + /// A base class for lazily resolving types for a resolver + /// + /// + /// + /// + /// This is a special case resolver for when types get lazily resolved in order to resolve the actual types. This is useful + /// for when there is some processing overhead (i.e. Type finding in assemblies) to return the Types used to instantiate the instances. + /// In some these cases we don't want to have to type find during application startup, only when we need to resolve the instances. + /// + /// Important notes about this resolver: This does not support Insert or Remove and therefore does not support any ordering unless + /// the types are marked with the WeightedPluginAttribute. + /// + internal abstract class LazyManyObjectsResolverBase : ManyObjectsResolverBase + where TResolved : class + where TResolver : class + { + #region Constructors + + protected LazyManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : base(scope) + { + } + + protected LazyManyObjectsResolverBase(HttpContextBase httpContext) + : base(httpContext) + { + } + + /// + /// Constructor accepting a list of lazy types + /// + /// + /// + protected LazyManyObjectsResolverBase(IEnumerable> listOfLazyTypes, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(scope) + { + AddTypes(listOfLazyTypes); + } + + /// + /// Constructor accepting a delegate to return a list of types + /// + /// + /// + protected LazyManyObjectsResolverBase(Func> typeListDelegate, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) + : this(scope) + { + _listOfTypeListDelegates.Add(typeListDelegate); + } + + /// + /// Constructor accepting a list of lazy types + /// + /// + /// + protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable> listOfLazyTypes) + : this(httpContext) + { + AddTypes(listOfLazyTypes); + } + + /// + /// Constructor accepting a delegate to return a list of types + /// + /// + /// + protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func> typeListDelegate) + : this(httpContext) + { + _listOfTypeListDelegates.Add(typeListDelegate); + } + + #endregion + + private readonly List> _lazyTypeList = new List>(); + private readonly List>> _listOfTypeListDelegates = new List>>(); + private List _resolvedTypes = null; + private readonly ReaderWriterLockSlim _typeResolutionLock = new ReaderWriterLockSlim(); + + /// + /// Used for unit tests + /// + internal bool HasResolvedTypes + { + get { return _resolvedTypes != null; } + } + + /// + /// Once this is called this will resolve all types registered in the lazy list + /// + protected override IEnumerable InstanceTypes + { + get + { + using (var lck = new UpgradeableReadLock(_typeResolutionLock)) + { + var lazyTypeList = _lazyTypeList.Select(x => x.Value).ToArray(); + var listofTypeListDelegates = _listOfTypeListDelegates.SelectMany(x => x()).ToArray(); + + //we need to validate each resolved type now since we could not do it before when inserting the lazy delegates + if (!HasResolvedTypes) + { + lck.UpgradeToWriteLock(); + + _resolvedTypes = new List(); + + //first iterate the lazy type list + foreach (var l in lazyTypeList) + { + UpdateUniqueList(_resolvedTypes, l); + } + + //next iterate the list of list type delegates + foreach (var l in listofTypeListDelegates) + { + UpdateUniqueList(_resolvedTypes, l); + } + } + + return _resolvedTypes; + } + } + } + + private void UpdateUniqueList(List uniqueList, Type toAdd) + { + EnsureCorrectType(toAdd); + if (uniqueList.Contains(toAdd)) + { + throw new InvalidOperationException("The Type " + toAdd + " already exists in the collection"); + } + uniqueList.Add(toAdd); + } + + /// + /// Allows adding of multiple lazy types at once + /// + /// + protected void AddTypes(IEnumerable> types) + { + EnsureAddSupport(); + + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) + { + foreach (var t in types) + { + _lazyTypeList.Add(t); + } + } + } + + /// + /// Adds a type list delegate to the collection + /// + /// + public void AddTypeListDelegate(Func> typeListDelegate) + { + EnsureAddSupport(); + + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) + { + _listOfTypeListDelegates.Add(typeListDelegate); + } + } + + /// + /// Adds a lazy type to the list + /// + /// + public void AddType(Lazy value) + { + EnsureAddSupport(); + + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) + { + _lazyTypeList.Add(value); + } + } + + /// + /// Converts the static type added to a lazy type and adds it to the internal list + /// + /// + public override void AddType(Type value) + { + AddType(new Lazy(() => value)); + } + + /// + /// Clears all lazy types + /// + public override void Clear() + { + EnsureClearSupport(); + + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) + { + _lazyTypeList.Clear(); + } + } + + /// + /// Does not support removal + /// + protected override bool SupportsRemove + { + get { return false; } + } + + /// + /// Does not support insert + /// + protected override bool SupportsInsert + { + get { return false; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs b/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs index f45e7fa9df..18d67f3b41 100644 --- a/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs +++ b/src/Umbraco.Core/ObjectResolution/LegacyTransientObjectsResolver.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.ObjectResolution /// these old classes don't contain metadata, the objects need to be instantiated first to get their metadata, we then store this /// for use in the GetById method. /// - internal abstract class LegacyTransientObjectsResolver : ManyObjectsResolverBase + internal abstract class LegacyTransientObjectsResolver : LazyManyObjectsResolverBase where TResolved : class where TResolver : class { @@ -27,16 +27,15 @@ namespace Umbraco.Core.ObjectResolution /// /// Constructor /// - /// + /// /// /// We are creating Transient instances (new instances each time) because this is how the legacy code worked and /// I don't want to muck anything up by changing them to application based instances. /// TODO: However, it would make much more sense to do this and would speed up the application plus this would make the GetById method much easier. /// - protected LegacyTransientObjectsResolver(IEnumerable refreshers) - : base(ObjectLifetimeScope.Transient) // new objects every time - { - AddTypes(refreshers); + protected LegacyTransientObjectsResolver(Func> types) + : base(types, ObjectLifetimeScope.Transient) // new objects every time + { } #endregion @@ -55,7 +54,7 @@ namespace Umbraco.Core.ObjectResolution protected abstract Guid GetUniqueIdentifier(TResolved obj); /// - /// Returns a new ICacheRefresher instance by id + /// Returns a new TResolved instance by id /// /// /// diff --git a/src/Umbraco.Core/ObjectResolution/MacroFieldEditorsResolver.cs b/src/Umbraco.Core/ObjectResolution/MacroFieldEditorsResolver.cs index 348ed699d3..f0b6867a38 100644 --- a/src/Umbraco.Core/ObjectResolution/MacroFieldEditorsResolver.cs +++ b/src/Umbraco.Core/ObjectResolution/MacroFieldEditorsResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Web; using System.Web.UI; using Umbraco.Core.Macros; @@ -14,14 +15,14 @@ namespace Umbraco.Core.ObjectResolution /// Much of this classes methods are based on legacy code from umbraco.editorControls.macrocontainer.MacroControlFactory /// this code should probably be reviewed and cleaned up if necessary. /// - internal sealed class MacroFieldEditorsResolver : ManyObjectsResolverBase + internal sealed class MacroFieldEditorsResolver : LazyManyObjectsResolverBase { /// /// Constructor /// /// - internal MacroFieldEditorsResolver(IEnumerable macroEditors) + internal MacroFieldEditorsResolver(Func> macroEditors) : base(macroEditors, ObjectLifetimeScope.Transient) { @@ -56,7 +57,7 @@ namespace Umbraco.Core.ObjectResolution /// internal List MacroControlTypes { - get { return InstanceTypes; } + get { return InstanceTypes.ToList(); } } /// diff --git a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs index 2172fe9102..9343b1a58b 100644 --- a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs +++ b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs @@ -6,14 +6,14 @@ using System.Web; namespace Umbraco.Core.ObjectResolution { - internal abstract class ManyObjectsResolverBase : ResolverBase where TResolved : class where TResolver : class { private List _applicationInstances = null; private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); - + private readonly List _instanceTypes = new List(); + #region Constructors @@ -34,7 +34,7 @@ namespace Umbraco.Core.ObjectResolution } LifetimeScope = scope; - InstanceTypes = new List(); + _instanceTypes = new List(); } /// @@ -48,7 +48,7 @@ namespace Umbraco.Core.ObjectResolution if (httpContext == null) throw new ArgumentNullException("httpContext"); LifetimeScope = ObjectLifetimeScope.HttpRequest; CurrentHttpContext = httpContext; - InstanceTypes = new List(); + _instanceTypes = new List(); } /// @@ -58,8 +58,8 @@ namespace Umbraco.Core.ObjectResolution /// If set to true will resolve singleton objects which will be created once for the lifetime of the application protected ManyObjectsResolverBase(IEnumerable value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application) : this(scope) - { - InstanceTypes = new List(value); + { + _instanceTypes = new List(value); } /// @@ -71,7 +71,7 @@ namespace Umbraco.Core.ObjectResolution protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable value) : this(httpContext) { - InstanceTypes = new List(value); + _instanceTypes = new List(value); } #endregion @@ -83,7 +83,10 @@ namespace Umbraco.Core.ObjectResolution /// /// Returns the list of Types registered that instances will be created from /// - protected List InstanceTypes { get; private set; } + protected virtual IEnumerable InstanceTypes + { + get { return _instanceTypes; } + } /// /// Returns the Current HttpContextBase used to construct this object if one exists. @@ -97,11 +100,7 @@ namespace Umbraco.Core.ObjectResolution protected ObjectLifetimeScope LifetimeScope { get; private set; } private int _defaultPluginWeight = 10; - private bool _supportsAdd = true; - private bool _supportsInsert = true; - private bool _supportsClear = true; - private bool _supportsRemove = true; - + /// /// Used in conjunction with GetSortedValues and WeightedPluginAttribute, if any of the objects /// being resolved do not contain the WeightedPluginAttribute then this will be the default weight applied @@ -189,15 +188,16 @@ namespace Umbraco.Core.ObjectResolution /// Removes a type. /// /// The type to remove. - public void RemoveType(Type value) + public virtual void RemoveType(Type value) { - if (!SupportsRemove) - throw new InvalidOperationException("This resolver does not support Removing types"); + EnsureRemoveSupport(); - using (new WriteLock(_lock)) + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) { EnsureCorrectType(value); - InstanceTypes.Remove(value); + _instanceTypes.Remove(value); } } @@ -215,8 +215,12 @@ namespace Umbraco.Core.ObjectResolution /// /// protected void AddTypes(IEnumerable types) - { - using (var l = new WriteLock(_lock)) + { + EnsureAddSupport(); + + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) { foreach(var t in types) { @@ -225,7 +229,7 @@ namespace Umbraco.Core.ObjectResolution { throw new InvalidOperationException("The Type " + t + " already exists in the collection"); }; - InstanceTypes.Add(t); + _instanceTypes.Add(t); } } } @@ -234,19 +238,20 @@ namespace Umbraco.Core.ObjectResolution /// Adds a Type to the end of the list. /// /// The object to be added. - public void AddType(Type value) + public virtual void AddType(Type value) { - if (!SupportsAdd) - throw new InvalidOperationException("This resolver does not support Adding new types"); + EnsureAddSupport(); - using (var l = new WriteLock(_lock)) + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) { EnsureCorrectType(value); if (InstanceTypes.Contains(value)) { throw new InvalidOperationException("The Type " + value + " already exists in the collection"); }; - InstanceTypes.Add(value); + _instanceTypes.Add(value); } } @@ -262,14 +267,15 @@ namespace Umbraco.Core.ObjectResolution /// /// Clears the list. /// - public void Clear() + public virtual void Clear() { - if (!SupportsClear) - throw new InvalidOperationException("This resolver does not support Clearing types"); + EnsureClearSupport(); - using (new WriteLock(_lock)) + EnsureResolutionNotFrozen(); + + using (GetWriteLock()) { - InstanceTypes.Clear(); + _instanceTypes.Clear(); } } @@ -278,12 +284,13 @@ namespace Umbraco.Core.ObjectResolution /// /// The zero-based index at which the object should be inserted. /// The object to insert. - public void InsertType(int index, Type value) + public virtual void InsertType(int index, Type value) { - if (!SupportsInsert) - throw new InvalidOperationException("This resolver does not support Inserting new types"); + EnsureInsertSupport(); - using (var l = new UpgradeableReadLock(_lock)) + EnsureResolutionNotFrozen(); + + using (var l = GetWriteLock()) { EnsureCorrectType(value); if (InstanceTypes.Contains(value)) @@ -291,8 +298,7 @@ namespace Umbraco.Core.ObjectResolution throw new InvalidOperationException("The Type " + value + " already exists in the collection"); }; - l.UpgradeToWriteLock(); - InstanceTypes.Insert(index, value); + _instanceTypes.Insert(index, value); } } @@ -306,7 +312,65 @@ namespace Umbraco.Core.ObjectResolution InsertType(index, typeof (T)); } - private void EnsureCorrectType(Type t) + /// + /// Returns a WriteLock to use when modifying collections + /// + /// + protected WriteLock GetWriteLock() + { + return new WriteLock(_lock); + } + + /// + /// Throws an exception if resolution is frozen + /// + protected void EnsureResolutionNotFrozen() + { + if (Resolution.IsFrozen) + throw new InvalidOperationException("The type list cannot be modified after resolution has been frozen"); + } + + /// + /// Throws an exception if this does not support Remove + /// + protected void EnsureRemoveSupport() + { + if (!SupportsRemove) + throw new InvalidOperationException("This resolver does not support Removing types"); + } + + /// + /// Throws an exception if this does not support Clear + /// + protected void EnsureClearSupport() + { + if (!SupportsClear) + throw new InvalidOperationException("This resolver does not support Clearing types"); + } + + /// + /// Throws an exception if this does not support Add + /// + protected void EnsureAddSupport() + { + if (!SupportsAdd) + throw new InvalidOperationException("This resolver does not support Adding new types"); + } + + /// + /// Throws an exception if this does not support insert + /// + protected void EnsureInsertSupport() + { + if (!SupportsInsert) + throw new InvalidOperationException("This resolver does not support Inserting new types"); + } + + /// + /// Throws an exception if the type is not of the TResolved type + /// + /// + protected void EnsureCorrectType(Type t) { if (!TypeHelper.IsTypeAssignableFrom(t)) throw new InvalidOperationException("The resolver " + this.GetType() + " can only accept types of " + typeof(TResolved) + ". The Type passed in to this method is " + t); @@ -314,22 +378,22 @@ namespace Umbraco.Core.ObjectResolution protected virtual bool SupportsAdd { - get { return _supportsAdd; } + get { return true; } } protected virtual bool SupportsInsert { - get { return _supportsInsert; } + get { return true; } } protected virtual bool SupportsClear { - get { return _supportsClear; } + get { return true; } } protected virtual bool SupportsRemove { - get { return _supportsRemove; } + get { return true; } } } } \ No newline at end of file diff --git a/src/Umbraco.Core/PackageActionsResolver.cs b/src/Umbraco.Core/PackageActionsResolver.cs index 8c1d412374..551bf8cfa7 100644 --- a/src/Umbraco.Core/PackageActionsResolver.cs +++ b/src/Umbraco.Core/PackageActionsResolver.cs @@ -8,14 +8,14 @@ namespace Umbraco.Core /// /// A resolver to return all IPackageAction objects /// - internal sealed class PackageActionsResolver : ManyObjectsResolverBase + internal sealed class PackageActionsResolver : LazyManyObjectsResolverBase { /// /// Constructor /// /// - internal PackageActionsResolver(IEnumerable packageActions) + internal PackageActionsResolver(Func> packageActions) : base(packageActions) { diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorValueConvertersResolver.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorValueConvertersResolver.cs index aaf1c06102..f804f424a6 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorValueConvertersResolver.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorValueConvertersResolver.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.PropertyEditors /// /// Manages the list of IPropertyEditorValueConverter's /// - internal class PropertyEditorValueConvertersResolver : ManyObjectsResolverBase + internal sealed class PropertyEditorValueConvertersResolver : ManyObjectsResolverBase { public PropertyEditorValueConvertersResolver(IEnumerable converters) : base(converters) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index da443413c7..38bd853e11 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -24,9 +24,7 @@ namespace Umbraco.Core.Services { private readonly IDatabaseUnitOfWorkProvider _uowProvider; private readonly IPublishingStrategy _publishingStrategy; - private readonly IUserService _userService; private readonly RepositoryFactory _repositoryFactory; - private HttpContextBase _httpContext; public ContentService() : this(new RepositoryFactory()) @@ -44,21 +42,13 @@ namespace Umbraco.Core.Services : this(provider, repositoryFactory, new PublishingStrategy()) { } - internal ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy) + public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy) { _uowProvider = provider; _publishingStrategy = publishingStrategy; _repositoryFactory = repositoryFactory; } - internal ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IPublishingStrategy publishingStrategy, IUserService userService) - { - _uowProvider = provider; - _publishingStrategy = publishingStrategy; - _userService = userService; - _repositoryFactory = repositoryFactory; - } - /// /// Creates an object using the alias of the /// that this Content is based on. @@ -68,7 +58,7 @@ namespace Umbraco.Core.Services /// Alias of the /// Optional id of the user creating the content /// - public IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = -1) + public IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = 0) { IContentType contentType = null; IContent content = null; @@ -95,8 +85,8 @@ namespace Umbraco.Core.Services if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parentId), this)) return content; - SetUser(content, userId); - SetWriter(content, userId); + content.CreatorId = userId; + content.WriterId = userId; Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parentId), this); @@ -377,7 +367,7 @@ namespace Umbraco.Core.Services /// /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - public bool RePublishAll(int userId = -1) + public bool RePublishAll(int userId = 0) { return RePublishAllDo(false, userId); } @@ -388,7 +378,7 @@ namespace Umbraco.Core.Services /// The to publish /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - public bool Publish(IContent content, int userId = -1) + public bool Publish(IContent content, int userId = 0) { return SaveAndPublishDo(content, false, userId); } @@ -399,7 +389,7 @@ namespace Umbraco.Core.Services /// The to publish along with its children /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - public bool PublishWithChildren(IContent content, int userId = -1) + public bool PublishWithChildren(IContent content, int userId = 0) { return PublishWithChildrenDo(content, false, userId); } @@ -410,7 +400,7 @@ namespace Umbraco.Core.Services /// The to publish /// Optional Id of the User issueing the publishing /// True if unpublishing succeeded, otherwise False - public bool UnPublish(IContent content, int userId = -1) + public bool UnPublish(IContent content, int userId = 0) { return UnPublishDo(content, false, userId); } @@ -421,7 +411,7 @@ namespace Umbraco.Core.Services /// The to save and publish /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - public bool SaveAndPublish(IContent content, int userId = -1) + public bool SaveAndPublish(IContent content, int userId = 0) { return SaveAndPublishDo(content, false, userId); } @@ -431,7 +421,7 @@ namespace Umbraco.Core.Services /// /// The to save /// Optional Id of the User saving the Content - public void Save(IContent content, int userId = -1) + public void Save(IContent content, int userId = 0) { Save(content, true, userId); } @@ -445,7 +435,7 @@ namespace Umbraco.Core.Services /// /// Collection of to save /// Optional Id of the User saving the Content - public void Save(IEnumerable contents, int userId = -1) + public void Save(IEnumerable contents, int userId = 0) { if (Saving.IsRaisedEventCancelled(new SaveEventArgs(contents), this)) return; @@ -459,7 +449,7 @@ namespace Umbraco.Core.Services { foreach (var content in contents) { - SetWriter(content, userId); + content.WriterId = userId; //Only change the publish state if the "previous" version was actually published if (content.Published) @@ -473,7 +463,7 @@ namespace Umbraco.Core.Services { foreach (var content in contents) { - SetWriter(content, userId); + content.WriterId = userId; repository.AddOrUpdate(content); } uow.Commit(); @@ -491,7 +481,7 @@ namespace Umbraco.Core.Services /// This needs extra care and attention as its potentially a dangerous and extensive operation /// Id of the /// Optional Id of the user issueing the delete operation - public void DeleteContentOfType(int contentTypeId, int userId = -1) + public void DeleteContentOfType(int contentTypeId, int userId = 0) { using (var uow = _uowProvider.GetUnitOfWork()) { @@ -523,7 +513,7 @@ namespace Umbraco.Core.Services Audit.Add(AuditTypes.Delete, string.Format("Delete Content of Type {0} performed by user", contentTypeId), - userId == -1 ? 0 : userId, -1); + userId, -1); } /// @@ -535,7 +525,7 @@ namespace Umbraco.Core.Services /// Please note that this method will completely remove the Content from the database /// The to delete /// Optional Id of the User deleting the Content - public void Delete(IContent content, int userId = -1) + public void Delete(IContent content, int userId = 0) { if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(content), this)) return; @@ -556,15 +546,13 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { - //TODO: Why are we setting a writer if we are just deleting the object? (I'm probably overlooking something here...?) - SetWriter(content, userId); repository.Delete(content); uow.Commit(); } Deleted.RaiseEvent(new DeleteEventArgs(content, false), this); - Audit.Add(AuditTypes.Delete, "Delete Content performed by user", userId == -1 ? 0 : userId, content.Id); + Audit.Add(AuditTypes.Delete, "Delete Content performed by user", userId, content.Id); } /// @@ -573,7 +561,7 @@ namespace Umbraco.Core.Services /// Id of the object to delete versions from /// Latest version date /// Optional Id of the User deleting versions of a Content object - public void DeleteVersions(int id, DateTime versionDate, int userId = -1) + public void DeleteVersions(int id, DateTime versionDate, int userId = 0) { //TODO: We should check if we are going to delete the most recent version because if that happens it means the // entity is completely deleted and we should raise the normal Deleting/Deleted event @@ -590,7 +578,7 @@ namespace Umbraco.Core.Services DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate), this); - Audit.Add(AuditTypes.Delete, "Delete Content by version date performed by user", userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Delete, "Delete Content by version date performed by user", userId, -1); } /// @@ -600,7 +588,7 @@ namespace Umbraco.Core.Services /// Id of the version to delete /// Boolean indicating whether to delete versions prior to the versionId /// Optional Id of the User deleting versions of a Content object - public void DeleteVersion(int id, Guid versionId, bool deletePriorVersions, int userId = -1) + public void DeleteVersion(int id, Guid versionId, bool deletePriorVersions, int userId = 0) { //TODO: We should check if we are going to delete the most recent version because if that happens it means the // entity is completely deleted and we should raise the normal Deleting/Deleted event @@ -623,7 +611,7 @@ namespace Umbraco.Core.Services DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, specificVersion:versionId), this); - Audit.Add(AuditTypes.Delete, "Delete Content by version performed by user", userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Delete, "Delete Content by version performed by user", userId, -1); } /// @@ -632,7 +620,7 @@ namespace Umbraco.Core.Services /// Move an item to the Recycle Bin will result in the item being unpublished /// The to delete /// Optional Id of the User deleting the Content - public void MoveToRecycleBin(IContent content, int userId = -1) + public void MoveToRecycleBin(IContent content, int userId = 0) { if (Trashing.IsRaisedEventCancelled(new MoveEventArgs(content, -20), this)) return; @@ -653,7 +641,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { - SetWriter(content, userId); + content.WriterId = userId; content.ChangeTrashedState(true); repository.AddOrUpdate(content); uow.Commit(); @@ -661,8 +649,7 @@ namespace Umbraco.Core.Services Trashed.RaiseEvent(new MoveEventArgs(content, false, -20), this); - Audit.Add(AuditTypes.Move, "Move Content to Recycle Bin performed by user", userId == -1 ? 0 : userId, - content.Id); + Audit.Add(AuditTypes.Move, "Move Content to Recycle Bin performed by user", userId, content.Id); } /// @@ -676,7 +663,7 @@ namespace Umbraco.Core.Services /// The to move /// Id of the Content's new Parent /// Optional Id of the User moving the Content - public void Move(IContent content, int parentId, int userId = -1) + public void Move(IContent content, int parentId, int userId = 0) { //This ensures that the correct method is called if this method is used to Move to recycle bin. if (parentId == -20) @@ -688,7 +675,7 @@ namespace Umbraco.Core.Services if (Moving.IsRaisedEventCancelled(new MoveEventArgs(content, parentId), this)) return; - SetWriter(content, userId); + content.WriterId = userId; var parent = GetById(parentId); content.Path = string.Concat(parent.Path, ",", content.Id); content.Level = parent.Level + 1; @@ -746,7 +733,7 @@ namespace Umbraco.Core.Services Moved.RaiseEvent(new MoveEventArgs(content, false, parentId), this); - Audit.Add(AuditTypes.Move, "Move Content performed by user", userId == -1 ? 0 : userId, content.Id); + Audit.Add(AuditTypes.Move, "Move Content performed by user", userId, content.Id); } /// @@ -786,7 +773,7 @@ namespace Umbraco.Core.Services /// Boolean indicating whether the copy should be related to the original /// Optional Id of the User copying the Content /// The newly created object - public IContent Copy(IContent content, int parentId, bool relateToOriginal, int userId = -1) + public IContent Copy(IContent content, int parentId, bool relateToOriginal, int userId = 0) { var copy = ((Content)content).Clone(); copy.ParentId = parentId; @@ -800,8 +787,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { - SetWriter(content, userId); - + content.WriterId = userId; repository.AddOrUpdate(copy); uow.Commit(); @@ -895,7 +881,7 @@ namespace Umbraco.Core.Services /// The to send to publication /// Optional Id of the User issueing the send to publication /// True if sending publication was succesfull otherwise false - internal bool SendToPublication(IContent content, int userId = -1) + internal bool SendToPublication(IContent content, int userId = 0) { if (SendingToPublish.IsRaisedEventCancelled(new SendToPublishEventArgs(content), this)) @@ -922,7 +908,7 @@ namespace Umbraco.Core.Services /// Id of the version to rollback to /// Optional Id of the User issueing the rollback of the Content /// The newly created object - public IContent Rollback(int id, Guid versionId, int userId = -1) + public IContent Rollback(int id, Guid versionId, int userId = 0) { var content = GetByVersion(versionId); @@ -932,8 +918,8 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { - SetUser(content, userId); - SetWriter(content, userId); + content.WriterId = userId; + content.CreatorId = userId; repository.AddOrUpdate(content); uow.Commit(); @@ -947,22 +933,13 @@ namespace Umbraco.Core.Services } #region Internal Methods - /// - /// Internal method to set the HttpContextBase for testing. - /// - /// - internal void SetHttpContext(HttpContextBase httpContext) - { - _httpContext = httpContext; - } - /// /// Internal method to Re-Publishes all Content for legacy purposes. /// /// Optional Id of the User issueing the publishing /// Optional boolean to avoid having the cache refreshed when calling this RePublish method. By default this method will not update the cache. /// True if publishing succeeded, otherwise False - internal bool RePublishAll(bool omitCacheRefresh = true, int userId = -1) + internal bool RePublishAll(bool omitCacheRefresh = true, int userId = 0) { return RePublishAllDo(omitCacheRefresh, userId); } @@ -974,7 +951,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will not update the cache. /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - internal bool Publish(IContent content, bool omitCacheRefresh = true, int userId = -1) + internal bool Publish(IContent content, bool omitCacheRefresh = true, int userId = 0) { return SaveAndPublishDo(content, omitCacheRefresh, userId); } @@ -986,7 +963,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will not update the cache. /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - internal bool PublishWithChildren(IContent content, bool omitCacheRefresh = true, int userId = -1) + internal bool PublishWithChildren(IContent content, bool omitCacheRefresh = true, int userId = 0) { return PublishWithChildrenDo(content, omitCacheRefresh, userId); } @@ -998,7 +975,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Unpublish method. By default this method will not update the cache. /// Optional Id of the User issueing the publishing /// True if unpublishing succeeded, otherwise False - internal bool UnPublish(IContent content, bool omitCacheRefresh = true, int userId = -1) + internal bool UnPublish(IContent content, bool omitCacheRefresh = true, int userId = 0) { return UnPublishDo(content, omitCacheRefresh, userId); } @@ -1010,7 +987,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will not update the cache. /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - internal bool SaveAndPublish(IContent content, bool omitCacheRefresh = true, int userId = -1) + internal bool SaveAndPublish(IContent content, bool omitCacheRefresh = true, int userId = 0) { return SaveAndPublishDo(content, omitCacheRefresh, userId); } @@ -1025,7 +1002,7 @@ namespace Umbraco.Core.Services /// Optional Id of the User issueing the publishing /// Optional boolean to avoid having the cache refreshed when calling this RePublish method. By default this method will update the cache. /// True if publishing succeeded, otherwise False - private bool RePublishAllDo(bool omitCacheRefresh = false, int userId = -1) + private bool RePublishAllDo(bool omitCacheRefresh = false, int userId = 0) { var list = new List(); var updated = new List(); @@ -1039,7 +1016,7 @@ namespace Umbraco.Core.Services if (content.IsValid()) { list.Add(content); - list.AddRange(GetChildrenDeep(content.Id)); + list.AddRange(GetDescendants(content)); } } @@ -1053,7 +1030,7 @@ namespace Umbraco.Core.Services //Only loop through content where the Published property has been updated foreach (var item in list.Where(x => ((ICanBeDirty)x).IsPropertyDirty("Published"))) { - SetWriter(item, userId); + item.WriterId = userId; repository.AddOrUpdate(item); updated.Add(item); } @@ -1076,7 +1053,7 @@ namespace Umbraco.Core.Services _publishingStrategy.PublishingFinalized(updated, true); } - Audit.Add(AuditTypes.Publish, "RePublish All performed by user", userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Publish, "RePublish All performed by user", userId, -1); return published; } @@ -1088,7 +1065,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will update the cache. /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - private bool PublishWithChildrenDo(IContent content, bool omitCacheRefresh = false, int userId = -1) + private bool PublishWithChildrenDo(IContent content, bool omitCacheRefresh = false, int userId = 0) { //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false) @@ -1115,7 +1092,7 @@ namespace Umbraco.Core.Services var updated = new List(); var list = new List(); list.Add(content); - list.AddRange(GetChildrenDeep(content.Id)); + list.AddRange(GetDescendants(content)); //Publish and then update the database with new status var published = _publishingStrategy.PublishWithChildren(list, userId); @@ -1127,7 +1104,7 @@ namespace Umbraco.Core.Services //Only loop through content where the Published property has been updated foreach (var item in list.Where(x => ((ICanBeDirty)x).IsPropertyDirty("Published"))) { - SetWriter(item, userId); + item.WriterId = userId; repository.AddOrUpdate(item); updated.Add(item); } @@ -1149,8 +1126,7 @@ namespace Umbraco.Core.Services if (omitCacheRefresh == false) _publishingStrategy.PublishingFinalized(updated, false); - Audit.Add(AuditTypes.Publish, "Publish with Children performed by user", userId == -1 ? 0 : userId, - content.Id); + Audit.Add(AuditTypes.Publish, "Publish with Children performed by user", userId, content.Id); } return published; @@ -1163,7 +1139,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Unpublish method. By default this method will update the cache. /// Optional Id of the User issueing the publishing /// True if unpublishing succeeded, otherwise False - private bool UnPublishDo(IContent content, bool omitCacheRefresh = false, int userId = -1) + private bool UnPublishDo(IContent content, bool omitCacheRefresh = false, int userId = 0) { var unpublished = _publishingStrategy.UnPublish(content, userId); if (unpublished) @@ -1171,6 +1147,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { + content.WriterId = userId; repository.AddOrUpdate(content); //Remove 'published' xml from the cmsContentXml table for the unpublished content @@ -1182,7 +1159,7 @@ namespace Umbraco.Core.Services if (omitCacheRefresh == false) _publishingStrategy.UnPublishingFinalized(content); - Audit.Add(AuditTypes.UnPublish, "UnPublish performed by user", userId == -1 ? 0 : userId, content.Id); + Audit.Add(AuditTypes.UnPublish, "UnPublish performed by user", userId, content.Id); } return unpublished; @@ -1195,7 +1172,7 @@ namespace Umbraco.Core.Services /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will update the cache. /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False - private bool SaveAndPublishDo(IContent content, bool omitCacheRefresh = false, int userId = -1) + private bool SaveAndPublishDo(IContent content, bool omitCacheRefresh = false, int userId = 0) { if (Saving.IsRaisedEventCancelled(new SaveEventArgs(content), this)) return false; @@ -1227,7 +1204,8 @@ namespace Umbraco.Core.Services using (var repository = _repositoryFactory.CreateContentRepository(uow)) { //Since this is the Save and Publish method, the content should be saved even though the publish fails or isn't allowed - SetWriter(content, userId); + content.WriterId = userId; + repository.AddOrUpdate(content); uow.Commit(); @@ -1259,7 +1237,7 @@ namespace Umbraco.Core.Services _publishingStrategy.PublishingFinalized(shouldBeRepublished, false); } - Audit.Add(AuditTypes.Publish, "Save and Publish performed by user", userId == -1 ? 0 : userId, content.Id); + Audit.Add(AuditTypes.Publish, "Save and Publish performed by user", userId, content.Id); return published; } @@ -1270,7 +1248,7 @@ namespace Umbraco.Core.Services /// The to save /// Boolean indicating whether or not to change the Published state upon saving /// Optional Id of the User saving the Content - private void Save(IContent content, bool changeState, int userId = -1) + private void Save(IContent content, bool changeState, int userId = 0) { if (Saving.IsRaisedEventCancelled(new SaveEventArgs(content), this)) return; @@ -1278,7 +1256,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { - SetWriter(content, userId); + content.WriterId = userId; //Only change the publish state if the "previous" version was actually published if (changeState && content.Published) @@ -1290,33 +1268,7 @@ namespace Umbraco.Core.Services Saved.RaiseEvent(new SaveEventArgs(content, false), this); - Audit.Add(AuditTypes.Save, "Save Content performed by user", userId == -1 ? 0 : userId, content.Id); - } - - /// - /// Gets a flat list of decendents of content from parent id - /// - /// - /// Only contains valid objects, which means - /// that everything in the returned list can be published. - /// If an invalid object is found it will not - /// be added to the list neither will its children. - /// - /// Id of the parent to retrieve children from - /// A list of valid that can be published - private IEnumerable GetChildrenDeep(int parentId) - { - var list = new List(); - var children = GetChildren(parentId); - foreach (var child in children) - { - if (child.IsValid()) - { - list.Add(child); - list.AddRange(GetChildrenDeep(child.Id)); - } - } - return list; + Audit.Add(AuditTypes.Save, "Save Content performed by user", userId, content.Id); } /// @@ -1353,63 +1305,6 @@ namespace Umbraco.Core.Services return true; } - /// - /// Updates a content object with the User (id), who created the content. - /// - /// object to update - /// Optional Id of the User - private void SetUser(IContent content, int userId) - { - if (userId > -1) - { - //If a user id was passed in we use that - content.CreatorId = userId; - } - else if (UserServiceOrContext()) - { - var profile = _httpContext == null - ? _userService.GetCurrentBackOfficeUser() - : _userService.GetCurrentBackOfficeUser(_httpContext); - content.CreatorId = profile.Id.SafeCast(); - } - else - { - //Otherwise we default to Admin user, which should always exist (almost always) - content.CreatorId = 0; - } - } - - /// - /// Updates a content object with a Writer (user id), who updated the content. - /// - /// object to update - /// Optional Id of the Writer - private void SetWriter(IContent content, int userId) - { - if (userId > -1) - { - //If a user id was passed in we use that - content.WriterId = userId; - } - else if (UserServiceOrContext()) - { - var profile = _httpContext == null - ? _userService.GetCurrentBackOfficeUser() - : _userService.GetCurrentBackOfficeUser(_httpContext); - content.WriterId = profile.Id.SafeCast(); - } - else - { - //Otherwise we default to Admin user, which should always exist (almost always) - content.WriterId = 0; - } - } - - private bool UserServiceOrContext() - { - return _userService != null && (HttpContext.Current != null || _httpContext != null); - } - #endregion #region Event Handlers diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs index bae66f95a5..0af521dddd 100644 --- a/src/Umbraco.Core/Services/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/ContentTypeService.cs @@ -1,9 +1,7 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Web; using Umbraco.Core.Auditing; using Umbraco.Core.Configuration; using Umbraco.Core.Events; @@ -23,9 +21,7 @@ namespace Umbraco.Core.Services private readonly RepositoryFactory _repositoryFactory; private readonly IContentService _contentService; private readonly IMediaService _mediaService; - private readonly IUserService _userService; private readonly IDatabaseUnitOfWorkProvider _uowProvider; - private HttpContextBase _httpContext; public ContentTypeService(IContentService contentService, IMediaService mediaService) : this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory(), contentService, mediaService) @@ -43,15 +39,6 @@ namespace Umbraco.Core.Services _mediaService = mediaService; } - internal ContentTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IContentService contentService, IMediaService mediaService, IUserService userService) - { - _uowProvider = provider; - _repositoryFactory = repositoryFactory; - _contentService = contentService; - _mediaService = mediaService; - _userService = userService; - } - /// /// Gets an object by its Id /// @@ -129,7 +116,7 @@ namespace Umbraco.Core.Services /// /// to save /// Optional id of the user saving the ContentType - public void Save(IContentType contentType, int userId = -1) + public void Save(IContentType contentType, int userId = 0) { if (SavingContentType.IsRaisedEventCancelled(new SaveEventArgs(contentType), this)) return; @@ -137,7 +124,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentTypeRepository(uow)) { - SetUser(contentType, userId); + contentType.CreatorId = userId; repository.AddOrUpdate(contentType); uow.Commit(); @@ -145,7 +132,7 @@ namespace Umbraco.Core.Services SavedContentType.RaiseEvent(new SaveEventArgs(contentType, false), this); } - Audit.Add(AuditTypes.Save, string.Format("Save ContentType performed by user"), userId == -1 ? 0 : userId, contentType.Id); + Audit.Add(AuditTypes.Save, string.Format("Save ContentType performed by user"), userId, contentType.Id); } /// @@ -153,7 +140,7 @@ namespace Umbraco.Core.Services /// /// Collection of to save /// Optional id of the user saving the ContentType - public void Save(IEnumerable contentTypes, int userId = -1) + public void Save(IEnumerable contentTypes, int userId = 0) { if (SavingContentType.IsRaisedEventCancelled(new SaveEventArgs(contentTypes), this)) return; @@ -163,7 +150,7 @@ namespace Umbraco.Core.Services { foreach (var contentType in contentTypes) { - SetUser(contentType, userId); + contentType.CreatorId = userId; repository.AddOrUpdate(contentType); } @@ -173,7 +160,7 @@ namespace Umbraco.Core.Services SavedContentType.RaiseEvent(new SaveEventArgs(contentTypes, false), this); } - Audit.Add(AuditTypes.Save, string.Format("Save ContentTypes performed by user"), userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Save, string.Format("Save ContentTypes performed by user"), userId, -1); } /// @@ -182,7 +169,7 @@ namespace Umbraco.Core.Services /// to delete /// Optional id of the user issueing the delete /// Deleting a will delete all the objects based on this - public void Delete(IContentType contentType, int userId = -1) + public void Delete(IContentType contentType, int userId = 0) { if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs(contentType), this)) return; @@ -198,7 +185,7 @@ namespace Umbraco.Core.Services DeletedContentType.RaiseEvent(new DeleteEventArgs(contentType, false), this); } - Audit.Add(AuditTypes.Delete, string.Format("Delete ContentType performed by user"), userId == -1 ? 0 : userId, contentType.Id); + Audit.Add(AuditTypes.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id); } /// @@ -209,7 +196,7 @@ namespace Umbraco.Core.Services /// /// Deleting a will delete all the objects based on this /// - public void Delete(IEnumerable contentTypes, int userId = -1) + public void Delete(IEnumerable contentTypes, int userId = 0) { if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs(contentTypes), this)) return; @@ -233,7 +220,7 @@ namespace Umbraco.Core.Services DeletedContentType.RaiseEvent(new DeleteEventArgs(contentTypes, false), this); } - Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1); } /// @@ -313,7 +300,7 @@ namespace Umbraco.Core.Services /// /// to save /// Optional Id of the user saving the MediaType - public void Save(IMediaType mediaType, int userId = -1) + public void Save(IMediaType mediaType, int userId = 0) { if (SavingMediaType.IsRaisedEventCancelled(new SaveEventArgs(mediaType), this)) return; @@ -321,14 +308,14 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow)) { - SetUser(mediaType, userId); + mediaType.CreatorId = userId; repository.AddOrUpdate(mediaType); uow.Commit(); SavedMediaType.RaiseEvent(new SaveEventArgs(mediaType, false), this); } - Audit.Add(AuditTypes.Save, string.Format("Save MediaType performed by user"), userId == -1 ? 0 : userId, mediaType.Id); + Audit.Add(AuditTypes.Save, string.Format("Save MediaType performed by user"), userId, mediaType.Id); } /// @@ -336,7 +323,7 @@ namespace Umbraco.Core.Services /// /// Collection of to save /// Optional Id of the user savging the MediaTypes - public void Save(IEnumerable mediaTypes, int userId = -1) + public void Save(IEnumerable mediaTypes, int userId = 0) { if (SavingMediaType.IsRaisedEventCancelled(new SaveEventArgs(mediaTypes), this)) return; @@ -347,7 +334,7 @@ namespace Umbraco.Core.Services foreach (var mediaType in mediaTypes) { - SetUser(mediaType, userId); + mediaType.CreatorId = userId; repository.AddOrUpdate(mediaType); } @@ -357,7 +344,7 @@ namespace Umbraco.Core.Services SavedMediaType.RaiseEvent(new SaveEventArgs(mediaTypes, false), this); } - Audit.Add(AuditTypes.Save, string.Format("Save MediaTypes performed by user"), userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Save, string.Format("Save MediaTypes performed by user"), userId, -1); } /// @@ -366,7 +353,7 @@ namespace Umbraco.Core.Services /// to delete /// Optional Id of the user deleting the MediaType /// Deleting a will delete all the objects based on this - public void Delete(IMediaType mediaType, int userId = -1) + public void Delete(IMediaType mediaType, int userId = 0) { if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs(mediaType), this)) return; @@ -383,7 +370,7 @@ namespace Umbraco.Core.Services DeletedMediaType.RaiseEvent(new DeleteEventArgs(mediaType, false), this); } - Audit.Add(AuditTypes.Delete, string.Format("Delete MediaType performed by user"), userId == -1 ? 0 : userId, mediaType.Id); + Audit.Add(AuditTypes.Delete, string.Format("Delete MediaType performed by user"), userId, mediaType.Id); } /// @@ -392,7 +379,7 @@ namespace Umbraco.Core.Services /// Collection of to delete /// /// Deleting a will delete all the objects based on this - public void Delete(IEnumerable mediaTypes, int userId = -1) + public void Delete(IEnumerable mediaTypes, int userId = 0) { if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs(mediaTypes), this)) return; @@ -415,7 +402,7 @@ namespace Umbraco.Core.Services DeletedMediaType.RaiseEvent(new DeleteEventArgs(mediaTypes, false), this); } - Audit.Add(AuditTypes.Delete, string.Format("Delete MediaTypes performed by user"), userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Delete, string.Format("Delete MediaTypes performed by user"), userId, -1); } /// @@ -473,46 +460,6 @@ namespace Umbraco.Core.Services return dtd.ToString(); } - /// - /// Internal method to set the HttpContextBase for testing. - /// - /// - internal void SetHttpContext(HttpContextBase httpContext) - { - _httpContext = httpContext; - } - - /// - /// Updates a content object with the User (id), who created the content. - /// - /// ContentType object to update - /// Optional Id of the User - private void SetUser(IContentTypeBase contentType, int userId) - { - if (userId > -1) - { - //If a user id was passed in we use that - contentType.CreatorId = userId; - } - else if (UserServiceOrContext()) - { - var profile = _httpContext == null - ? _userService.GetCurrentBackOfficeUser() - : _userService.GetCurrentBackOfficeUser(_httpContext); - contentType.CreatorId = profile.Id.SafeCast(); - } - else - { - //Otherwise we default to Admin user, which should always exist (almost always) - contentType.CreatorId = 0; - } - } - - private bool UserServiceOrContext() - { - return _userService != null && (HttpContext.Current != null || _httpContext != null); - } - #region Event Handlers /// diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 49ad5953a4..50ef680d1c 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -117,7 +117,7 @@ namespace Umbraco.Core.Services /// /// to save /// Id of the user issueing the save - public void Save(IDataTypeDefinition dataTypeDefinition, int userId = -1) + public void Save(IDataTypeDefinition dataTypeDefinition, int userId = 0) { if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinition), this)) return; @@ -125,14 +125,14 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow)) { - dataTypeDefinition.CreatorId = userId > -1 ? userId : 0; + dataTypeDefinition.CreatorId = userId; repository.AddOrUpdate(dataTypeDefinition); uow.Commit(); Saved.RaiseEvent(new SaveEventArgs(dataTypeDefinition, false), this); } - Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId == -1 ? 0 : userId, dataTypeDefinition.Id); + Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id); } /// @@ -144,7 +144,7 @@ namespace Umbraco.Core.Services /// /// to delete /// Optional Id of the user issueing the deletion - public void Delete(IDataTypeDefinition dataTypeDefinition, int userId = -1) + public void Delete(IDataTypeDefinition dataTypeDefinition, int userId = 0) { if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(dataTypeDefinition), this)) return; @@ -181,7 +181,7 @@ namespace Umbraco.Core.Services Deleted.RaiseEvent(new DeleteEventArgs(dataTypeDefinition, false), this); } - Audit.Add(AuditTypes.Delete, string.Format("Delete DataTypeDefinition performed by user"), userId == -1 ? 0 : userId, dataTypeDefinition.Id); + Audit.Add(AuditTypes.Delete, string.Format("Delete DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id); } /// diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 4130da307a..ace5d1d612 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -63,7 +63,7 @@ namespace Umbraco.Core.Services /// /// to save /// - public void SaveStylesheet(Stylesheet stylesheet, int userId = -1) + public void SaveStylesheet(Stylesheet stylesheet, int userId = 0) { if (SavingStylesheet.IsRaisedEventCancelled(new SaveEventArgs(stylesheet), this)) return; @@ -77,7 +77,7 @@ namespace Umbraco.Core.Services SavedStylesheet.RaiseEvent(new SaveEventArgs(stylesheet, false), this); } - Audit.Add(AuditTypes.Save, string.Format("Save Stylesheet performed by user"), userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Save, string.Format("Save Stylesheet performed by user"), userId, -1); } /// @@ -85,7 +85,7 @@ namespace Umbraco.Core.Services /// /// Name incl. extension of the Stylesheet to delete /// - public void DeleteStylesheet(string name, int userId = -1) + public void DeleteStylesheet(string name, int userId = 0) { var uow = _fileUowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateStylesheetRepository(uow)) @@ -100,7 +100,7 @@ namespace Umbraco.Core.Services DeletedStylesheet.RaiseEvent(new DeleteEventArgs(stylesheet, false), this); - Audit.Add(AuditTypes.Delete, string.Format("Delete Stylesheet performed by user"), userId == -1 ? 0 : userId, -1); + Audit.Add(AuditTypes.Delete, string.Format("Delete Stylesheet performed by user"), userId, -1); } } @@ -144,7 +144,7 @@ namespace Umbraco.Core.Services /// /// to save /// - public void SaveScript(Script script, int userId = -1) + public void SaveScript(Script script, int userId = 0) { if (SavingScript.IsRaisedEventCancelled(new SaveEventArgs