public void Delete(IEnumerable <TItem> items, int userId = Cms.Core.Constants.Security.SuperUserId)
        {
            TItem[] itemsA = items.ToArray();

            using (IScope scope = ScopeProvider.CreateScope())
            {
                EventMessages eventMessages = EventMessagesFactory.Get();
                DeletingNotification <TItem> deletingNotification = GetDeletingNotification(itemsA, eventMessages);
                if (scope.Notifications.PublishCancelable(deletingNotification))
                {
                    scope.Complete();
                    return;
                }

                scope.WriteLock(WriteLockIds);

                // all descendants are going to be deleted
                TItem[] allDescendantsAndSelf = itemsA.SelectMany(xx => GetDescendants(xx.Id, true))
                                                .DistinctBy(x => x.Id)
                                                .ToArray();
                TItem[] deleted = allDescendantsAndSelf;

                // all impacted (through composition) probably lose some properties
                // don't try to be too clever here, just report them all
                // do this before anything is deleted
                TItem[] changed = allDescendantsAndSelf.SelectMany(x => GetComposedOf(x.Id))
                                  .Distinct()
                                  .Except(allDescendantsAndSelf)
                                  .ToArray();

                // delete content
                DeleteItemsOfTypes(allDescendantsAndSelf.Select(x => x.Id));

                // finally delete the content types
                // (see notes in overload)
                foreach (TItem item in itemsA)
                {
                    Repository.Delete(item);
                }

                ContentTypeChange <TItem>[] changes = allDescendantsAndSelf.Select(x => new ContentTypeChange <TItem>(x, ContentTypeChangeTypes.Remove))
                                                      .Concat(changed.Select(x => new ContentTypeChange <TItem>(x, ContentTypeChangeTypes.RefreshMain | ContentTypeChangeTypes.RefreshOther)))
                                                      .ToArray();

                // Publish this in scope, see comment at GetContentTypeRefreshedNotification for more info.
                _eventAggregator.Publish(GetContentTypeRefreshedNotification(changes, eventMessages));

                scope.Notifications.Publish(GetContentTypeChangedNotification(changes, eventMessages));

                DeletedNotification <TItem> deletedNotification = GetDeletedNotification(deleted.DistinctBy(x => x.Id), eventMessages);
                deletedNotification.WithStateFrom(deletingNotification);
                scope.Notifications.Publish(deletedNotification);

                Audit(AuditType.Delete, userId, -1);
                scope.Complete();
            }
        }
        public void Delete(TItem item, int userId = Cms.Core.Constants.Security.SuperUserId)
        {
            using (IScope scope = ScopeProvider.CreateScope())
            {
                EventMessages eventMessages = EventMessagesFactory.Get();
                DeletingNotification <TItem> deletingNotification = GetDeletingNotification(item, eventMessages);
                if (scope.Notifications.PublishCancelable(deletingNotification))
                {
                    scope.Complete();
                    return;
                }

                scope.WriteLock(WriteLockIds);

                // all descendants are going to be deleted
                TItem[] descendantsAndSelf = GetDescendants(item.Id, true)
                                             .ToArray();
                TItem[] deleted = descendantsAndSelf;

                // all impacted (through composition) probably lose some properties
                // don't try to be too clever here, just report them all
                // do this before anything is deleted
                TItem[] changed = descendantsAndSelf.SelectMany(xx => GetComposedOf(xx.Id))
                                  .Distinct()
                                  .Except(descendantsAndSelf)
                                  .ToArray();

                // delete content
                DeleteItemsOfTypes(descendantsAndSelf.Select(x => x.Id));

                // Next find all other document types that have a reference to this content type
                IEnumerable <TItem> referenceToAllowedContentTypes = GetAll().Where(q => q.AllowedContentTypes.Any(p => p.Id.Value == item.Id));
                foreach (TItem reference in referenceToAllowedContentTypes)
                {
                    reference.AllowedContentTypes = reference.AllowedContentTypes.Where(p => p.Id.Value != item.Id);
                    var changedRef = new List <ContentTypeChange <TItem> >()
                    {
                        new ContentTypeChange <TItem>(reference, ContentTypeChangeTypes.RefreshMain)
                    };
                    // Fire change event
                    scope.Notifications.Publish(GetContentTypeChangedNotification(changedRef, eventMessages));
                }

                // finally delete the content type
                // - recursively deletes all descendants
                // - deletes all associated property data
                //  (contents of any descendant type have been deleted but
                //   contents of any composed (impacted) type remain but
                //   need to have their property data cleared)
                Repository.Delete(item);

                ContentTypeChange <TItem>[] changes = descendantsAndSelf.Select(x => new ContentTypeChange <TItem>(x, ContentTypeChangeTypes.Remove))
                                                      .Concat(changed.Select(x => new ContentTypeChange <TItem>(x, ContentTypeChangeTypes.RefreshMain | ContentTypeChangeTypes.RefreshOther)))
                                                      .ToArray();

                // Publish this in scope, see comment at GetContentTypeRefreshedNotification for more info.
                _eventAggregator.Publish(GetContentTypeRefreshedNotification(changes, eventMessages));

                scope.Notifications.Publish(GetContentTypeChangedNotification(changes, eventMessages));

                DeletedNotification <TItem> deletedNotification = GetDeletedNotification(deleted.DistinctBy(x => x.Id), eventMessages);
                deletedNotification.WithStateFrom(deletingNotification);
                scope.Notifications.Publish(deletedNotification);

                Audit(AuditType.Delete, userId, item.Id);
                scope.Complete();
            }
        }