diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs
index 70cb877183..d7db11dc3b 100644
--- a/src/Umbraco.Core/Models/Content.cs
+++ b/src/Umbraco.Core/Models/Content.cs
@@ -267,6 +267,9 @@ namespace Umbraco.Core.Models
[IgnoreDataMember]
internal DateTime PublishedDate { get; set; }
+ [DataMember]
+ public bool IsBlueprint { get; internal set; }
+
///
/// Changes the Trashed state of the content object
///
@@ -330,7 +333,7 @@ namespace Umbraco.Core.Models
//turn off change tracking
clone.DisableChangeTracking();
//need to manually clone this since it's not settable
- clone._contentType = (IContentType)ContentType.DeepClone();
+ clone._contentType = (IContentType)ContentType.DeepClone();
//this shouldn't really be needed since we're not tracking
clone.ResetDirtyProperties(false);
//re-enable tracking
diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs
index 7caefc1121..3c92b17ae6 100644
--- a/src/Umbraco.Core/Models/IContent.cs
+++ b/src/Umbraco.Core/Models/IContent.cs
@@ -84,6 +84,11 @@ namespace Umbraco.Core.Models
///
/// Gets the unique identifier of the published version, if any.
///
- Guid PublishedVersionGuid { get; }
+ Guid PublishedVersionGuid { get; }
+
+ ///
+ /// Gets a value indicating whether the content item is a blueprint.
+ ///
+ bool IsBlueprint { get; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs
index c44c8ac1dc..c019b694d2 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs
@@ -95,8 +95,5 @@ namespace Umbraco.Core.Persistence.Repositories
///
///
void AddOrUpdatePreviewXml(IContent content, Func xml);
-
-
-
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs
index 491e03a065..8cfe67b99b 100644
--- a/src/Umbraco.Core/Services/ContentService.cs
+++ b/src/Umbraco.Core/Services/ContentService.cs
@@ -177,7 +177,7 @@ namespace Umbraco.Core.Services
content.WriterId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs(content, false, contentTypeAlias, parentId));
-
+
uow.Commit();
}
@@ -219,7 +219,7 @@ namespace Umbraco.Core.Services
content.WriterId = userId;
uow.Events.Dispatch(Created, this, new NewEventArgs(content, false, contentTypeAlias, parent));
-
+
uow.Commit();
}
@@ -269,7 +269,7 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(content);
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
- uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false));
+ uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false), "Saved");
uow.Events.Dispatch(Created, this, new NewEventArgs(content, false, contentTypeAlias, parentId));
Audit(uow, AuditType.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
@@ -324,7 +324,7 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(content);
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
- uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false));
+ uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false), "Saved");
uow.Events.Dispatch(Created, this, new NewEventArgs(content, false, contentTypeAlias, parent));
Audit(uow, AuditType.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
@@ -1161,14 +1161,28 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateContentBlueprintRepository(uow);
- return repository.Get(id);
+ var blueprint = repository.Get(id);
+ ((Content) blueprint).IsBlueprint = true;
+ return blueprint;
}
}
+ public IContent GetBlueprintById(Guid id)
+ {
+ // the repository implements a cache policy on int identifiers, not guids,
+ // and we are not changing it now, but we still would like to rely on caching
+ // instead of running a full query against the database, so relying on the
+ // id-key map, which is fast.
+
+ var a = _idkMap.GetIdForKey(id, UmbracoObjectTypes.DocumentBlueprint);
+ return a.Success ? GetBlueprintById(a.Result) : null;
+ }
+
public void SaveBlueprint(IContent content, int userId = 0)
{
//always ensure the blueprint is at the root
- content.ParentId = -1;
+ content.ParentId = -1;
+ ((Content) content).IsBlueprint = true;
using (new WriteLock(Locker))
{
@@ -1186,8 +1200,10 @@ namespace Umbraco.Core.Services
content.CreatorId = userId;
}
content.WriterId = userId;
-
- repository.AddOrUpdate(content);
+
+ repository.AddOrUpdate(content);
+
+ uow.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs(content), "SavedBlueprint");
uow.Commit();
}
@@ -1199,9 +1215,10 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
using (var uow = UowProvider.GetUnitOfWork())
- {
+ {
var repository = RepositoryFactory.CreateContentBlueprintRepository(uow);
- repository.Delete(content);
+ repository.Delete(content);
+ uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs(content), "DeletedBlueprint");
uow.Commit();
}
}
@@ -1215,19 +1232,11 @@ namespace Umbraco.Core.Services
var content = new Content(name, -1, contentType);
content.Path = string.Concat(content.ParentId.ToString(), ",", content.Id);
- using (var uow = UowProvider.GetUnitOfWork())
- {
- content.CreatorId = userId;
- content.WriterId = userId;
+ content.CreatorId = userId;
+ content.WriterId = userId;
- //Now we need to map all of the properties over!
- foreach (var property in blueprint.Properties)
- {
- content.SetValue(property.Alias, property.Value);
- }
-
- uow.Commit();
- }
+ foreach (var property in blueprint.Properties)
+ content.SetValue(property.Alias, property.Value);
return content;
}
@@ -1298,7 +1307,7 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
- uow.Events.Dispatch(Saved, this, new SaveEventArgs(asArray, false, evtMsgs));
+ uow.Events.Dispatch(Saved, this, new SaveEventArgs(asArray, false, evtMsgs), "Saved");
Audit(uow, AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root);
uow.Commit();
@@ -1678,7 +1687,7 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(copy);
repository.AddOrUpdatePreviewXml(copy, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
-
+
//add permissions
if (currentPermissions.Count > 0)
{
@@ -1860,7 +1869,7 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
- uow.Events.Dispatch(Saved, this, new SaveEventArgs(asArray, false));
+ uow.Events.Dispatch(Saved, this, new SaveEventArgs(asArray, false), "Saved");
if (shouldBePublished.Any())
{
@@ -1887,7 +1896,11 @@ namespace Umbraco.Core.Services
{
query.Where(x => documentTypeIds.Contains(x.ContentTypeId));
}
- return repository.GetByQuery(query);
+ return repository.GetByQuery(query).Select(x =>
+ {
+ ((Content) x).IsBlueprint = true;
+ return x;
+ });
}
}
@@ -2294,7 +2307,7 @@ namespace Umbraco.Core.Services
}
if (raiseEvents)
- uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false, evtMsgs));
+ uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false, evtMsgs), "Saved");
//Save xml to db and call following method to fire event through PublishingStrategy to update cache
if (published)
@@ -2362,7 +2375,7 @@ namespace Umbraco.Core.Services
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
if (raiseEvents)
- uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false, evtMsgs));
+ uow.Events.Dispatch(Saved, this, new SaveEventArgs(content, false, evtMsgs), "Saved");
Audit(uow, AuditType.Save, "Save Content performed by user", userId, content.Id);
uow.Commit();
@@ -2625,6 +2638,17 @@ namespace Umbraco.Core.Services
/// Occurs after the Recycle Bin has been Emptied
///
public static event TypedEventHandler EmptiedRecycleBin;
+
+ ///
+ /// Occurs after a blueprint has been saved.
+ ///
+ public static event TypedEventHandler> SavedBlueprint;
+
+ ///
+ /// Occurs after a blueprint has been deleted.
+ ///
+ public static event TypedEventHandler> DeletedBlueprint;
+
#endregion
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs
index b048046ac0..e33f46e3f4 100644
--- a/src/Umbraco.Core/Services/IContentService.cs
+++ b/src/Umbraco.Core/Services/IContentService.cs
@@ -98,6 +98,7 @@ namespace Umbraco.Core.Services
{
IEnumerable GetBlueprintsForContentTypes(params int[] documentTypeIds);
IContent GetBlueprintById(int id);
+ IContent GetBlueprintById(Guid id);
void SaveBlueprint(IContent content, int userId = 0);
void DeleteBlueprint(IContent content, int userId = 0);
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
diff --git a/src/Umbraco.Core/UdiGetterExtensions.cs b/src/Umbraco.Core/UdiGetterExtensions.cs
index 4ae6b05dca..9f824f6a26 100644
--- a/src/Umbraco.Core/UdiGetterExtensions.cs
+++ b/src/Umbraco.Core/UdiGetterExtensions.cs
@@ -132,7 +132,7 @@ namespace Umbraco.Core
public static GuidUdi GetUdi(this IContent entity)
{
if (entity == null) throw new ArgumentNullException("entity");
- return new GuidUdi(Constants.UdiEntityType.Document, entity.Key).EnsureClosed();
+ return new GuidUdi(entity.IsBlueprint ? Constants.UdiEntityType.DocumentBluePrint : Constants.UdiEntityType.Document, entity.Key).EnsureClosed();
}
///
@@ -211,8 +211,8 @@ namespace Umbraco.Core
if (entity == null) throw new ArgumentNullException("entity");
// we should throw on Unknown but for the time being, assume it means PartialView
- var entityType = entity.ViewType == PartialViewType.PartialViewMacro
- ? Constants.UdiEntityType.PartialViewMacro
+ var entityType = entity.ViewType == PartialViewType.PartialViewMacro
+ ? Constants.UdiEntityType.PartialViewMacro
: Constants.UdiEntityType.PartialView;
return new StringUdi(entityType, entity.Path.TrimStart('/')).EnsureClosed();