using System; using System.Collections.Generic; using System.Linq; using System.Web; using Umbraco.Core.Auditing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; namespace Umbraco.Core.Services { /// /// Represents the Content Service, which is an easy access to operations involving /// public class ContentService : IContentService { private readonly IDatabaseUnitOfWorkProvider _uowProvider; private readonly IPublishingStrategy _publishingStrategy; private readonly IUserService _userService; private HttpContextBase _httpContext; public ContentService(IDatabaseUnitOfWorkProvider provider, IPublishingStrategy publishingStrategy) { _uowProvider = provider; _publishingStrategy = publishingStrategy; } internal ContentService(IDatabaseUnitOfWorkProvider provider, IPublishingStrategy publishingStrategy, IUserService userService) { _publishingStrategy = publishingStrategy; _userService = userService; _uowProvider = provider; } //TODO Add GetLatestUnpublishedVersions(int id){} /// /// Creates an object using the alias of the /// that this Content is based on. /// /// Id of Parent for the new Content /// Alias of the /// Optional id of the user creating the content /// public IContent CreateContent(int parentId, string contentTypeAlias, int userId = -1) { var uow = _uowProvider.GetUnitOfWork(); var repository = RepositoryResolver.Current.Factory.CreateContentTypeRepository(uow); var query = Query.Builder.Where(x => x.Alias == contentTypeAlias); var contentTypes = repository.GetByQuery(query); if (!contentTypes.Any()) throw new Exception(string.Format("No ContentType matching the passed in Alias: '{0}' was found", contentTypeAlias)); var contentType = contentTypes.First(); if (contentType == null) throw new Exception(string.Format("ContentType matching the passed in Alias: '{0}' was null", contentTypeAlias)); IContent content = null; var e = new NewEventArgs { Alias = contentTypeAlias, ParentId = parentId }; if (Creating != null) Creating(content, e); if (!e.Cancel) { content = new Content(parentId, contentType); SetUser(content, userId); SetWriter(content, userId); if (Created != null) Created(content, e); Audit.Add(AuditTypes.New, "", content.CreatorId, content.Id); } return content; } /// /// Gets an object by Id /// /// Id of the Content to retrieve /// public IContent GetById(int id) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { return repository.Get(id); } } /// /// Gets an object by its 'UniqueId' /// /// Guid key of the Content to retrieve /// public IContent GetById(Guid key) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.Key == key); var contents = repository.GetByQuery(query); return contents.SingleOrDefault(); } } /// /// Gets a collection of objects by the Id of the /// /// Id of the /// An Enumerable list of objects public IEnumerable GetContentOfContentType(int id) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ContentTypeId == id); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of objects by Level /// /// The level to retrieve Content from /// An Enumerable list of objects public IEnumerable GetByLevel(int level) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.Level == level); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of objects by Parent Id /// /// Id of the Parent to retrieve Children from /// An Enumerable list of objects public IEnumerable GetChildren(int id) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ParentId == id); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of an objects versions by Id /// /// /// An Enumerable list of objects public IEnumerable GetVersions(int id) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var versions = repository.GetAllVersions(id); return versions; } } /// /// Gets a collection of objects, which reside at the first level / root /// /// An Enumerable list of objects public IEnumerable GetRootContent() { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ParentId == -1); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of objects, which has an expiration date less than or equal to today. /// /// An Enumerable list of objects public IEnumerable GetContentForExpiration() { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.Published == true && x.ExpireDate <= DateTime.UtcNow); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of objects, which has a release date less than or equal to today. /// /// An Enumerable list of objects public IEnumerable GetContentForRelease() { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.Published == false && x.ReleaseDate <= DateTime.UtcNow); var contents = repository.GetByQuery(query); return contents; } } /// /// Gets a collection of an objects, which resides in the Recycle Bin /// /// An Enumerable list of objects public IEnumerable GetContentInRecycleBin() { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { var query = Query.Builder.Where(x => x.ParentId == -20); var contents = repository.GetByQuery(query); return contents; } } /// /// Re-Publishes all Content /// /// Optional Id of the User issueing the publishing /// True if publishing succeeded, otherwise False public bool RePublishAll(int userId = -1) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var list = new List(); //Consider creating a Path query instead of recursive method: //var query = Query.Builder.Where(x => x.Path.StartsWith("-1")); var rootContent = GetRootContent(); foreach (var content in rootContent) { if (content.IsValid()) { list.Add(content); list.AddRange(GetChildrenDeep(content.Id)); } } //Publish and then update the database with new status var published = _publishingStrategy.PublishWithChildren(list, userId); if (published) { //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); repository.AddOrUpdate(item); } uow.Commit(); //TODO Change this so we can avoid a depencency to the horrible library method / umbraco.content (singleton) class. //global::umbraco.library.RefreshContent(); Audit.Add(AuditTypes.Publish, "RePublish All performed by user", userId == -1 ? 0 : userId, -1); } return published; } } /// /// Publishes a single object /// /// 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) { return SaveAndPublish(content, userId); } /// /// Publishes a object and all its children /// /// 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) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { //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 && !GetById(content.ParentId).Published) { LogHelper.Info( string.Format("Content '{0}' with Id '{1}' could not be published because its parent is not published.", content.Name, content.Id)); return false; } //Content contains invalid property values and can therefore not be published - fire event? if (!content.IsValid()) { LogHelper.Info( string.Format("Content '{0}' with Id '{1}' could not be published because of invalid properties.", content.Name, content.Id)); return false; } //Consider creating a Path query instead of recursive method: //var query = Query.Builder.Where(x => x.Path.StartsWith(content.Path)); var list = new List(); list.Add(content); list.AddRange(GetChildrenDeep(content.Id)); //Publish and then update the database with new status var published = _publishingStrategy.PublishWithChildren(list, userId); if (published) { //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); repository.AddOrUpdate(item); } uow.Commit(); //TODO Change this so we can avoid a depencency to the horrible library method / umbraco.content (singleton) class. //TODO Need to investigate if it will also update the cache for children of the Content object //global::umbraco.library.UpdateDocumentCache(content.Id); Audit.Add(AuditTypes.Publish, "Publish with Children performed by user", userId == -1 ? 0 : userId, content.Id); } return published; } } /// /// UnPublishes a single object /// /// 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) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { //Look for children and unpublish them if any exists, otherwise just unpublish the passed in Content. var children = GetChildrenDeep(content.Id); var hasChildren = children.Any(); if (hasChildren) children.Add(content); var unpublished = hasChildren ? _publishingStrategy.UnPublish(children, userId) : _publishingStrategy.UnPublish(content, userId); if (unpublished) { repository.AddOrUpdate(content); if (hasChildren) { foreach (var child in children) { SetWriter(child, userId); repository.AddOrUpdate(child); } } uow.Commit(); //TODO Change this so we can avoid a depencency to the horrible library method / umbraco.content class. //global::umbraco.library.UnPublishSingleNode(content.Id); Audit.Add(AuditTypes.Publish, "UnPublish performed by user", userId == -1 ? 0 : userId, content.Id); } return unpublished; } } /// /// 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 List 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; } /// /// Saves and Publishes a single object /// /// 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) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var e = new SaveEventArgs(); if (Saving != null) Saving(content, e); if (!e.Cancel) { //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 && GetById(content.ParentId).Published == false) { LogHelper.Info( string.Format( "Content '{0}' with Id '{1}' could not be published because its parent is not published.", content.Name, content.Id)); return false; } //Content contains invalid property values and can therefore not be published - fire event? if (!content.IsValid()) { LogHelper.Info( string.Format( "Content '{0}' with Id '{1}' could not be published because of invalid properties.", content.Name, content.Id)); return false; } //Publish and then update the database with new status bool published = _publishingStrategy.Publish(content, userId); if (published) { SetWriter(content, userId); repository.AddOrUpdate(content); uow.Commit(); //TODO Change this so we can avoid a depencency to the horrible library method / umbraco.content (singleton) class. //global::umbraco.library.UpdateDocumentCache(content.Id); } if (Saved != null) Saved(content, e); Audit.Add(AuditTypes.Publish, "Save and Publish performed by user", userId == -1 ? 0 : userId, content.Id); return published; } return false; } } /// /// Saves a single object /// /// The to save /// Optional Id of the User saving the Content public void Save(IContent content, int userId = -1) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var e = new SaveEventArgs(); if (Saving != null) Saving(content, e); if (!e.Cancel) { SetWriter(content, userId); content.ChangePublishedState(false); repository.AddOrUpdate(content); uow.Commit(); if (Saved != null) Saved(content, e); Audit.Add(AuditTypes.Save, "Save Content performed by user", userId == -1 ? 0 : userId, content.Id); } } } /// /// Saves a collection of objects. /// /// /// If the collection of content contains new objects that references eachother by Id or ParentId, /// then use the overload Save method with a collection of Lazy . /// /// Collection of to save /// Optional Id of the User saving the Content public void Save(IEnumerable contents, int userId = -1) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var containsNew = contents.Any(x => x.HasIdentity == false); var e = new SaveEventArgs(); if (Saving != null) Saving(contents, e); if (!e.Cancel) { if (containsNew) { foreach (var content in contents) { SetWriter(content, userId); content.ChangePublishedState(false); repository.AddOrUpdate(content); uow.Commit(); } } else { foreach (var content in contents) { if (Saving != null) Saving(content, e); SetWriter(content, userId); repository.AddOrUpdate(content); } uow.Commit(); } if (Saved != null) Saved(contents, e); Audit.Add(AuditTypes.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, -1); } } } /// /// Saves a collection of lazy loaded objects. /// /// /// This method ensures that Content is saved lazily, so a new graph of /// objects can be saved in bulk. But note that objects are saved one at a time to ensure Ids. /// /// Collection of Lazy to save /// Optional Id of the User saving the Content public void Save(IEnumerable> contents, int userId = -1) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var e = new SaveEventArgs(); if (Saving != null) Saving(contents, e); if (!e.Cancel) { foreach (var content in contents) { SetWriter(content.Value, userId); content.Value.ChangePublishedState(false); repository.AddOrUpdate(content.Value); uow.Commit(); } if (Saved != null) Saved(contents, e); Audit.Add(AuditTypes.Save, "Bulk Save (lazy) content performed by user", userId == -1 ? 0 : userId, -1); } } } /// /// Deletes all content of specified type. All children of deleted content is moved to Recycle Bin. /// /// 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) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { //NOTE What about content that has the contenttype as part of its composition? var query = Query.Builder.Where(x => x.ContentTypeId == contentTypeId); var contents = repository.GetByQuery(query); var e = new DeleteEventArgs { Id = contentTypeId }; if (Deleting != null) Deleting(contents, e); if (!e.Cancel) { foreach (var content in contents) { ((Content)content).ChangeTrashedState(true); repository.AddOrUpdate(content); } uow.Commit(); if (Deleted != null) Deleted(contents, e); Audit.Add(AuditTypes.Delete, string.Format("Delete Content of Type {0} performed by user", contentTypeId), userId == -1 ? 0 : userId, -1); } } } /// /// Permanently deletes an object /// /// 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) { //TODO Ensure that content is unpublished when deleted //TODO This method should handle/react to errors when there is a constraint issue with the content being deleted //TODO Children should either be deleted or moved to the recycle bin var e = new DeleteEventArgs { Id = content.Id }; if (Deleting != null) Deleting(content, e); if (!e.Cancel) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { SetWriter(content, userId); repository.Delete(content); uow.Commit(); if (Deleted != null) Deleted(content, e); Audit.Add(AuditTypes.Delete, "Delete Content performed by user", userId == -1 ? 0 : userId, content.Id); } } } /// /// Permanently deletes versions from an object prior to a specific date. /// /// Id of the object to delete versions from /// Latest version date /// Optional Id of the User deleting versions of a Content object public void Delete(IContent content, DateTime versionDate, int userId = -1) { Delete(content.Id, versionDate, userId); } /// /// Permanently deletes specific version(s) from an object. /// /// Id of the object to delete a version from /// 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 Delete(IContent content, Guid versionId, bool deletePriorVersions, int userId = -1) { Delete(content.Id, versionId, deletePriorVersions, userId); } /// /// Permanently deletes versions from an object prior to a specific date. /// /// Id of the object to delete versions from /// Latest version date /// Optional Id of the User deleting versions of a Content object public void Delete(int id, DateTime versionDate, int userId = -1) { var e = new DeleteEventArgs { Id = id }; if (Deleting != null) Deleting(versionDate, e); if (!e.Cancel) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { repository.Delete(id, versionDate); if (Deleted != null) Deleted(versionDate, e); Audit.Add(AuditTypes.Delete, "Delete Content by version date performed by user", userId == -1 ? 0 : userId, -1); } } } /// /// Permanently deletes specific version(s) from an object. /// /// Id of the object to delete a version from /// 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 Delete(int id, Guid versionId, bool deletePriorVersions, int userId = -1) { using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(_uowProvider.GetUnitOfWork())) { if (deletePriorVersions) { var content = repository.GetByVersion(id, versionId); Delete(id, content.UpdateDate, userId); } var e = new DeleteEventArgs { Id = id }; if (Deleting != null) Deleting(versionId, e); if (!e.Cancel) { repository.Delete(id, versionId); if (Deleted != null) Deleted(versionId, e); Audit.Add(AuditTypes.Delete, "Delete Content by version performed by user", userId == -1 ? 0 : userId, -1); } } } /// /// Deletes an object by moving it to the Recycle Bin /// /// 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) { //TODO If content item has children those should also be moved to the recycle bin //TODO Unpublish deleted content + children var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var e = new MoveEventArgs { ParentId = -20 }; if (Trashing != null) Trashing(content, e); if (!e.Cancel) { SetWriter(content, userId); content.ChangeTrashedState(true); repository.AddOrUpdate(content); uow.Commit(); if (Trashed != null) Trashed(content, e); Audit.Add(AuditTypes.Move, "Move Content to Recycle Bin performed by user", userId == -1 ? 0 : userId, content.Id); } } } /// /// Moves an object to a new location by changing its parent id. /// /// /// If the object is already published it will be /// published after being moved to its new location. Otherwise it'll just /// be saved with a new parent id. /// /// 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) { var e = new MoveEventArgs { ParentId = parentId }; if (Moving != null) Moving(content, e); if (!e.Cancel) { SetWriter(content, userId); //If Content is being moved away from Recycle Bin, its state should be un-trashed if (content.Trashed && parentId != -20) { content.ChangeTrashedState(false, parentId); } else { content.ParentId = parentId; } //If Content is published, it should be (re)published from its new location if (content.Published) { SaveAndPublish(content, userId); } else { Save(content, userId); } if (Moved != null) Moved(content, e); Audit.Add(AuditTypes.Move, "Move Content performed by user", userId == -1 ? 0 : userId, content.Id); } } /// /// Empties the Recycle Bin by deleting all that resides in the bin /// public void EmptyRecycleBin() { var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var query = Query.Builder.Where(x => x.ParentId == -20); var contents = repository.GetByQuery(query); foreach (var content in contents) { repository.Delete(content); } uow.Commit(); Audit.Add(AuditTypes.Delete, "Empty Recycle Bin performed by user", 0, -20); } } /// /// Copies an object by creating a new Content object of the same type and copies all data from the current /// to the new copy which is returned. /// /// The to copy /// Id of the Content's new Parent /// Optional Id of the User copying the Content /// The newly created object public IContent Copy(IContent content, int parentId, int userId = -1) { var e = new CopyEventArgs { ParentId = parentId }; if (Copying != null) Copying(content, e); IContent copy = null; if (!e.Cancel) { copy = ((Content)content).Clone(); copy.ParentId = parentId; copy.Name = copy.Name + " (1)"; var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { SetWriter(content, userId); repository.AddOrUpdate(copy); uow.Commit(); } } if (Copied != null) Copied(copy, e); Audit.Add(AuditTypes.Delete, "Copy Content performed by user", content.WriterId, content.Id); return copy; } /// /// Sends an to Publication, which executes handlers and events for the 'Send to Publication' action. /// /// The to send to publication /// Optional Id of the User issueing the send to publication /// True if sending publication was succesfull otherwise false public bool SendToPublication(IContent content, int userId = -1) { //TODO Implement something similar to this var e = new SendToPublishEventArgs(); if (SendingToPublish != null) SendingToPublish(content, e); if (!e.Cancel) { // Do some stuff here.. if (SentToPublish != null) SentToPublish(content, e); Audit.Add(AuditTypes.SendToPublish, "Send to Publish performed by user", content.WriterId, content.Id); } /*SendToPublishEventArgs e = new SendToPublishEventArgs(); FireBeforeSendToPublish(e); if (!e.Cancel) { global::umbraco.BusinessLogic.Actions.Action.RunActionHandlers(content, ActionToPublish.Instance); FireAfterSendToPublish(e); return true; } return false;*/ return false; } /// /// Rollback an object to a previous version. /// This will create a new version, which is a copy of all the old data. /// /// /// The way data is stored actually only allows us to rollback on properties /// and not data like Name and Alias of the Content. /// /// Id of the being rolled back /// 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) { var e = new RollbackEventArgs(); var uow = _uowProvider.GetUnitOfWork(); using (var repository = RepositoryResolver.Current.Factory.CreateContentRepository(uow)) { var content = repository.GetByVersion(id, versionId); if (Rollingback != null) Rollingback(content, e); if (!e.Cancel) { SetUser(content, userId); SetWriter(content, userId); repository.AddOrUpdate(content); uow.Commit(); if (Rolledback != null) Rolledback(content, e); Audit.Add(AuditTypes.RollBack, "Content rollback performed by user", content.WriterId, content.Id); } return content; } } /// /// 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. /// /// 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); } #region Event Handlers /// /// Occurs before Delete /// public static event EventHandler Deleting; /// /// Occurs after Delete /// public static event EventHandler Deleted; /// /// Occurs before Save /// public static event EventHandler Saving; /// /// Occurs after Save /// public static event EventHandler Saved; /// /// Occurs before Create /// public static event EventHandler Creating; /// /// Occurs after Create /// public static event EventHandler Created; /// /// Occurs before Copy /// public static event EventHandler Copying; /// /// Occurs after Copy /// public static event EventHandler Copied; /// /// Occurs before Content is moved to Recycle Bin /// public static event EventHandler Trashing; /// /// Occurs after Content is moved to Recycle Bin /// public static event EventHandler Trashed; /// /// Occurs before Move /// public static event EventHandler Moving; /// /// Occurs after Move /// public static event EventHandler Moved; /// /// Occurs before Rollback /// public static event EventHandler Rollingback; /// /// Occurs after Rollback /// public static event EventHandler Rolledback; /// /// Occurs before Send to Publish /// public static event EventHandler SendingToPublish; /// /// Occurs after Send to Publish /// public static event EventHandler SentToPublish; #endregion } }