Backported changes from 6.1 to fix how RePublishAll behaves in the content service to ensure its the same as what was done with
Document.RePublishAll
This commit is contained in:
@@ -120,7 +120,17 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
public static void DropTable(this Database db, string tableName)
|
||||
{
|
||||
var sql = new Sql(string.Format("DROP TABLE {0}", SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)));
|
||||
var sql = new Sql(string.Format(
|
||||
SqlSyntaxContext.SqlSyntaxProvider.DropTable,
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)));
|
||||
db.Execute(sql);
|
||||
}
|
||||
|
||||
public static void TruncateTable(this Database db, string tableName)
|
||||
{
|
||||
var sql = new Sql(string.Format(
|
||||
SqlSyntaxContext.SqlSyntaxProvider.TruncateTable,
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(tableName)));
|
||||
db.Execute(sql);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
string InsertData { get; }
|
||||
string UpdateData { get; }
|
||||
string DeleteData { get; }
|
||||
string TruncateTable { get; }
|
||||
string CreateConstraint { get; }
|
||||
string DeleteConstraint { get; }
|
||||
string CreateForeignKeyConstraint { get; }
|
||||
|
||||
@@ -42,6 +42,14 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SqlCe doesn't support the Truncate Table syntax, so we just have to do a DELETE FROM which is slower but we have no choice.
|
||||
/// </summary>
|
||||
public override string TruncateTable
|
||||
{
|
||||
get { return "DELETE FROM {0}"; }
|
||||
}
|
||||
|
||||
public override string GetIndexType(IndexTypes indexTypes)
|
||||
{
|
||||
string indexType;
|
||||
|
||||
@@ -436,6 +436,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
public virtual string InsertData { get { return "INSERT INTO {0} ({1}) VALUES ({2})"; } }
|
||||
public virtual string UpdateData { get { return "UPDATE {0} SET {1} WHERE {2}"; } }
|
||||
public virtual string DeleteData { get { return "DELETE FROM {0} WHERE {1}"; } }
|
||||
public virtual string TruncateTable { get { return "TRUNCATE TABLE {0}"; } }
|
||||
|
||||
public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } }
|
||||
public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
@@ -22,6 +23,9 @@ namespace Umbraco.Core.Services
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IMediaService _mediaService;
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
//Support recursive locks because some of the methods that require locking call other methods that require locking.
|
||||
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
|
||||
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
|
||||
public ContentTypeService(IContentService contentService, IMediaService mediaService)
|
||||
: this(new PetaPocoUnitOfWorkProvider(), new RepositoryFactory(), contentService, mediaService)
|
||||
@@ -173,19 +177,22 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(contentType), this))
|
||||
return;
|
||||
|
||||
_contentService.DeleteContentOfType(contentType.Id);
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
repository.Delete(contentType);
|
||||
uow.Commit();
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
_contentService.DeleteContentOfType(contentType.Id);
|
||||
|
||||
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentType, false), this);
|
||||
}
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
repository.Delete(contentType);
|
||||
uow.Commit();
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
|
||||
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentType, false), this);
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentType performed by user"), userId, contentType.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -200,27 +207,30 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (DeletingContentType.IsRaisedEventCancelled(new DeleteEventArgs<IContentType>(contentTypes), this))
|
||||
return;
|
||||
|
||||
var contentTypeList = contentTypes.ToList();
|
||||
foreach (var contentType in contentTypeList)
|
||||
{
|
||||
_contentService.DeleteContentOfType(contentType.Id);
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
foreach (var contentType in contentTypeList)
|
||||
{
|
||||
repository.Delete(contentType);
|
||||
}
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var contentTypeList = contentTypes.ToList();
|
||||
foreach (var contentType in contentTypeList)
|
||||
{
|
||||
_contentService.DeleteContentOfType(contentType.Id);
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
foreach (var contentType in contentTypeList)
|
||||
{
|
||||
repository.Delete(contentType);
|
||||
}
|
||||
|
||||
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentTypes, false), this);
|
||||
}
|
||||
uow.Commit();
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
|
||||
DeletedContentType.RaiseEvent(new DeleteEventArgs<IContentType>(contentTypes, false), this);
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -357,20 +367,22 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(mediaType), this))
|
||||
return;
|
||||
|
||||
_mediaService.DeleteMediaOfType(mediaType.Id, userId);
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
_mediaService.DeleteMediaOfType(mediaType.Id, userId);
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
|
||||
repository.Delete(mediaType);
|
||||
uow.Commit();
|
||||
repository.Delete(mediaType);
|
||||
uow.Commit();
|
||||
|
||||
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaType, false), this);
|
||||
}
|
||||
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaType, false), this);
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaType performed by user"), userId, mediaType.Id);
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaType performed by user"), userId, mediaType.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -383,26 +395,28 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (DeletingMediaType.IsRaisedEventCancelled(new DeleteEventArgs<IMediaType>(mediaTypes), this))
|
||||
return;
|
||||
|
||||
var mediaTypeList = mediaTypes.ToList();
|
||||
foreach (var mediaType in mediaTypeList)
|
||||
{
|
||||
_mediaService.DeleteMediaOfType(mediaType.Id);
|
||||
}
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var mediaTypeList = mediaTypes.ToList();
|
||||
foreach (var mediaType in mediaTypeList)
|
||||
{
|
||||
_mediaService.DeleteMediaOfType(mediaType.Id);
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
foreach (var mediaType in mediaTypeList)
|
||||
{
|
||||
repository.Delete(mediaType);
|
||||
}
|
||||
uow.Commit();
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
foreach (var mediaType in mediaTypeList)
|
||||
{
|
||||
repository.Delete(mediaType);
|
||||
}
|
||||
uow.Commit();
|
||||
|
||||
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaTypes, false), this);
|
||||
}
|
||||
DeletedMediaType.RaiseEvent(new DeleteEventArgs<IMediaType>(mediaTypes, false), this);
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaTypes performed by user"), userId, -1);
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete MediaTypes performed by user"), userId, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Auditing;
|
||||
using Umbraco.Core.Events;
|
||||
@@ -19,6 +20,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
private readonly RepositoryFactory _repositoryFactory;
|
||||
//Support recursive locks because some of the methods that require locking call other methods that require locking.
|
||||
//for example, the Move method needs to be locked but this calls the Save method which also needs to be locked.
|
||||
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
|
||||
public MediaService(RepositoryFactory repositoryFactory)
|
||||
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
|
||||
@@ -306,32 +310,35 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Id of the User moving the Media</param>
|
||||
public void Move(IMedia media, 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 == -21)
|
||||
{
|
||||
MoveToRecycleBin(media, userId);
|
||||
return;
|
||||
}
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
//This ensures that the correct method is called if this method is used to Move to recycle bin.
|
||||
if (parentId == -21)
|
||||
{
|
||||
MoveToRecycleBin(media, userId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Moving.IsRaisedEventCancelled(new MoveEventArgs<IMedia>(media, parentId), this))
|
||||
return;
|
||||
if (Moving.IsRaisedEventCancelled(new MoveEventArgs<IMedia>(media, parentId), this))
|
||||
return;
|
||||
|
||||
media.ParentId = parentId;
|
||||
Save(media, userId);
|
||||
media.ParentId = parentId;
|
||||
Save(media, userId);
|
||||
|
||||
//Ensure that Path and Level is updated on children
|
||||
var children = GetChildren(media.Id);
|
||||
if (children.Any())
|
||||
{
|
||||
var parentPath = media.Path;
|
||||
var parentLevel = media.Level;
|
||||
var updatedDescendents = UpdatePathAndLevelOnChildren(children, parentPath, parentLevel);
|
||||
Save(updatedDescendents, userId);
|
||||
}
|
||||
//Ensure that Path and Level is updated on children
|
||||
var children = GetChildren(media.Id);
|
||||
if (children.Any())
|
||||
{
|
||||
var parentPath = media.Path;
|
||||
var parentLevel = media.Level;
|
||||
var updatedDescendents = UpdatePathAndLevelOnChildren(children, parentPath, parentLevel);
|
||||
Save(updatedDescendents, userId);
|
||||
}
|
||||
|
||||
Moved.RaiseEvent(new MoveEventArgs<IMedia>(media, false, parentId), this);
|
||||
Moved.RaiseEvent(new MoveEventArgs<IMedia>(media, false, parentId), this);
|
||||
|
||||
Audit.Add(AuditTypes.Move, "Move Media performed by user", userId, media.Id);
|
||||
Audit.Add(AuditTypes.Move, "Move Media performed by user", userId, media.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -403,32 +410,42 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="mediaTypeId">Id of the <see cref="IMediaType"/></param>
|
||||
/// <param name="userId">Optional id of the user deleting the media</param>
|
||||
public void DeleteMediaOfType(int mediaTypeId, int userId = 0)
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
//NOTE What about media that has the contenttype as part of its composition?
|
||||
//The ContentType has to be removed from the composition somehow as it would otherwise break
|
||||
//Dbl.check+test that the ContentType's Id is removed from the ContentType2ContentType table
|
||||
var query = Query<IMedia>.Builder.Where(x => x.ContentTypeId == mediaTypeId);
|
||||
var contents = repository.GetByQuery(query);
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
//NOTE What about media that has the contenttype as part of its composition?
|
||||
//The ContentType has to be removed from the composition somehow as it would otherwise break
|
||||
//Dbl.check+test that the ContentType's Id is removed from the ContentType2ContentType table
|
||||
var query = Query<IMedia>.Builder.Where(x => x.ContentTypeId == mediaTypeId);
|
||||
var contents = repository.GetByQuery(query);
|
||||
|
||||
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMedia>(contents), this))
|
||||
return;
|
||||
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMedia>(contents), this))
|
||||
return;
|
||||
|
||||
foreach (var content in contents)
|
||||
{
|
||||
((Core.Models.Media)content).ChangeTrashedState(true);
|
||||
repository.AddOrUpdate(content);
|
||||
}
|
||||
foreach (var content in contents.OrderByDescending(x => x.ParentId))
|
||||
{
|
||||
//Look for children of current content and move that to trash before the current content is deleted
|
||||
var c = content;
|
||||
var childQuery = Query<IMedia>.Builder.Where(x => x.Path.StartsWith(c.Path));
|
||||
var children = repository.GetByQuery(childQuery);
|
||||
|
||||
uow.Commit();
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (child.ContentType.Id != mediaTypeId)
|
||||
MoveToRecycleBin(child, userId);
|
||||
}
|
||||
|
||||
Deleted.RaiseEvent(new DeleteEventArgs<IMedia>(contents, false), this);
|
||||
}
|
||||
//Permantly delete the content
|
||||
Delete(content, userId);
|
||||
}
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, "Delete Media items by Type performed by user", userId, -1);
|
||||
}
|
||||
Audit.Add(AuditTypes.Delete, "Delete Media items by Type performed by user", userId, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Permanently deletes an <see cref="IMedia"/> object
|
||||
@@ -523,25 +540,28 @@ namespace Umbraco.Core.Services
|
||||
return;
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
uow.Commit();
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
media.CreatorId = userId;
|
||||
repository.AddOrUpdate(media);
|
||||
uow.Commit();
|
||||
|
||||
var xml = media.ToXml();
|
||||
var poco = new ContentXmlDto { NodeId = media.Id, Xml = xml.ToString(SaveOptions.None) };
|
||||
var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = media.Id }) != null;
|
||||
int result = exists
|
||||
? uow.Database.Update(poco)
|
||||
: Convert.ToInt32(uow.Database.Insert(poco));
|
||||
}
|
||||
var xml = media.ToXml();
|
||||
var poco = new ContentXmlDto {NodeId = media.Id, Xml = xml.ToString(SaveOptions.None)};
|
||||
var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new {Id = media.Id}) != null;
|
||||
int result = exists
|
||||
? uow.Database.Update(poco)
|
||||
: Convert.ToInt32(uow.Database.Insert(poco));
|
||||
}
|
||||
|
||||
if(raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
|
||||
|
||||
Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
|
||||
Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -298,18 +298,30 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = contentTypeService.GetContentType("umbTextpage");
|
||||
var rootContent = contentService.GetRootContent();
|
||||
foreach (var c in rootContent)
|
||||
{
|
||||
contentService.PublishWithChildren(c);
|
||||
}
|
||||
//for testing we need to clear out the contentXml table so we can see if it worked
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var uow = provider.GetUnitOfWork();
|
||||
using (RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
|
||||
{
|
||||
uow.Database.TruncateTable("cmsContentXml");
|
||||
}
|
||||
|
||||
// Act
|
||||
var published = contentService.RePublishAll(0);
|
||||
var contents = contentService.GetContentOfContentType(contentType.Id);
|
||||
|
||||
// Assert
|
||||
Assert.That(published, Is.True);
|
||||
Assert.That(contents.First(x => x.Id == 1046).Published, Is.True);//No restrictions, so should be published
|
||||
Assert.That(contents.First(x => x.Id == 1047).Published, Is.True);//Released 5 mins ago, so should be published
|
||||
Assert.That(contents.First(x => x.Id == 1049).Published, Is.False);//Trashed content, so shouldn't be published
|
||||
Assert.IsTrue(published);
|
||||
var allContent = rootContent.Concat(rootContent.SelectMany(x => contentService.GetDescendants(x.Id)));
|
||||
uow = provider.GetUnitOfWork();
|
||||
using (var repo = RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
|
||||
{
|
||||
Assert.AreEqual(allContent.Count(), uow.Database.ExecuteScalar<int>("select count(*) from cmsContentXml"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user