Ejemplo n.º 1
0
 private void CreateAndSaveMediaXml(XElement xml, int id, UmbracoDatabase db)
 {
     var poco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
     var exists = db.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = id }) != null;
     int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
 }
Ejemplo n.º 2
0
 private void CreateAndSaveContentXml(XElement xml, int id, UmbracoDatabase db)
 {
     var contentPoco = new ContentXmlDto { NodeId = id, Xml = xml.ToString(SaveOptions.None) };
     var contentExists = db.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = id }) != 0;
     int contentResult = contentExists ? db.Update(contentPoco) : Convert.ToInt32(db.Insert(contentPoco));
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Moves an <see cref="IContent"/> object to a new location by changing its parent id.
        /// </summary>
        /// <remarks>
        /// If the <see cref="IContent"/> 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.
        /// </remarks>
        /// <param name="content">The <see cref="IContent"/> to move</param>
        /// <param name="parentId">Id of the Content's new Parent</param>
        /// <param name="userId">Optional Id of the User moving the Content</param>
        public void Move(IContent content, int parentId, int userId = 0)
        {
            using (new WriteLock(Locker))
            {
                //This ensures that the correct method is called if this method is used to Move to recycle bin.
                if (parentId == -20)
                {
                    MoveToRecycleBin(content, userId);
                    return;
                }

                if (Moving.IsRaisedEventCancelled(new MoveEventArgs<IContent>(content, parentId), this))
                    return;

                content.WriterId = userId;
                if (parentId == -1)
                {
                    content.Path = string.Concat("-1,", content.Id);
                    content.Level = 1;
                }
                else
                {
                    var parent = GetById(parentId);
                    content.Path = string.Concat(parent.Path, ",", content.Id);
                    content.Level = parent.Level + 1;
                }


                //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)
                {
                    //If Content is Publishable its saved and published
                    //otherwise we save the content without changing the publish state, and generate new xml because the Path, Level and Parent has changed.
                    if (IsPublishable(content))
                    {
                        SaveAndPublish(content, userId);
                    }
                    else
                    {
                        Save(content, false, userId, true);

                        using (var uow = _uowProvider.GetUnitOfWork())
                        {
                            var xml = content.ToXml();
                            var poco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) };
                            var exists =
                                uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = content.Id }) !=
                                null;
                            int result = exists
                                             ? uow.Database.Update(poco)
                                             : Convert.ToInt32(uow.Database.Insert(poco));
                        }
                    }
                }
                else
                {
                    Save(content, userId);
                }

                //Ensure that Path and Level is updated on children
                var children = GetChildren(content.Id);
                if (children.Any())
                {
                    foreach (var child in children)
                    {
                        Move(child, content.Id, userId);
                    }
                }

                Moved.RaiseEvent(new MoveEventArgs<IContent>(content, false, parentId), this);

                Audit.Add(AuditTypes.Move, "Move Content performed by user", userId, content.Id);
            }
        }
Ejemplo n.º 4
0
	    /// <summary>
	    /// Publishes a <see cref="IContent"/> object and all its children
	    /// </summary>
	    /// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
	    /// <param name="userId">Optional Id of the User issueing the publishing</param>
	    /// <param name="includeUnpublished">If set to true, this will also publish descendants that are completely unpublished, normally this will only publish children that have previously been published</param>	    
	    /// <returns>
	    /// A list of publish statues. If the parent document is not valid or cannot be published because it's parent(s) is not published
	    /// then the list will only contain one status item, otherwise it will contain status items for it and all of it's descendants that
	    /// are to be published.
	    /// </returns>
	    private IEnumerable<Attempt<PublishStatus>> PublishWithChildrenDo(
            IContent content, int userId = 0, bool includeUnpublished = false)
        {
	        if (content == null) throw new ArgumentNullException("content");

	        using (new WriteLock(Locker))
	        {
                var result = new List<Attempt<PublishStatus>>();

                //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)
                {
                    LogHelper.Info<ContentService>(
                        string.Format(
                            "Content '{0}' with Id '{1}' could not be published because its parent or one of its ancestors is not published.",
                            content.Name, content.Id));
                    result.Add(new Attempt<PublishStatus>(false, new PublishStatus(content, PublishStatusType.FailedPathNotPublished)));
                    return result;
                }

                //Content contains invalid property values and can therefore not be published - fire event?
                if (!content.IsValid())
                {
                    LogHelper.Info<ContentService>(
                        string.Format("Content '{0}' with Id '{1}' could not be published because of invalid properties.",
                                      content.Name, content.Id));
                    result.Add(
                        new Attempt<PublishStatus>(false, 
                            new PublishStatus(content, PublishStatusType.FailedContentInvalid)
                                {
                                    InvalidProperties = ((ContentBase) content).LastInvalidProperties
                                }));
                    return result;
                }

                //Consider creating a Path query instead of recursive method:
                //var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith(content.Path));

                var updated = new List<IContent>();
                var list = new List<IContent>();
                list.Add(content); //include parent item
                list.AddRange(GetDescendants(content));

                var internalStrategy = (PublishingStrategy)_publishingStrategy;

                //Publish and then update the database with new status
                var publishedOutcome = internalStrategy.PublishWithChildrenInternal(list, userId, includeUnpublished).ToArray();

                var uow = _uowProvider.GetUnitOfWork();
                using (var repository = _repositoryFactory.CreateContentRepository(uow))
                {
                    //NOTE The Publish with subpages-dialog was used more as a republish-type-thing, so we'll have to include PublishStatusType.SuccessAlreadyPublished
                    //in the updated-list, so the Published event is triggered with the expected set of pages and the xml is updated.
                    foreach (var item in publishedOutcome.Where(
                        x => x.Success || x.Result.StatusType == PublishStatusType.SuccessAlreadyPublished))
                    {
                        item.Result.ContentItem.WriterId = userId;
                        repository.AddOrUpdate(item.Result.ContentItem);
                        updated.Add(item.Result.ContentItem);
                    }

                    uow.Commit();

                    foreach (var c in updated)
                    {
                        var xml = c.ToXml();
                        var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
                        var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = c.Id }) !=
                                        null;
                        var r = exists
                                    ? uow.Database.Update(poco)
                                    : Convert.ToInt32(uow.Database.Insert(poco));
                    }
                }
                //Save xml to db and call following method to fire event:
                _publishingStrategy.PublishingFinalized(updated, false);

                Audit.Add(AuditTypes.Publish, "Publish with Children performed by user", userId, content.Id);


                return publishedOutcome;
	        }	        
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Saves and Publishes a single <see cref="IContent"/> object
        /// </summary>
        /// <param name="content">The <see cref="IContent"/> to save and publish</param>
        /// <param name="omitCacheRefresh">Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will update the cache.</param>
        /// <param name="userId">Optional Id of the User issueing the publishing</param>
        /// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
        /// <returns>True if publishing succeeded, otherwise False</returns>
        private bool SaveAndPublishDo(IContent content, bool omitCacheRefresh = false, int userId = 0, bool raiseEvents = true)
        {
            if (raiseEvents)
            {
                if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IContent>(content), this))
                    return false;
            }

            using (new WriteLock(Locker))
            {
                //Has this content item previously been published? If so, we don't need to refresh the children
                var previouslyPublished = HasPublishedVersion(content.Id);
                var validForPublishing = true;

                //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)
                {
                    LogHelper.Info<ContentService>(
                        string.Format(
                            "Content '{0}' with Id '{1}' could not be published because its parent is not published.",
                            content.Name, content.Id));
                    validForPublishing = false;
                }

                //Content contains invalid property values and can therefore not be published - fire event?
                if (!content.IsValid())
                {
                    LogHelper.Info<ContentService>(
                        string.Format(
                            "Content '{0}' with Id '{1}' could not be published because of invalid properties.",
                            content.Name, content.Id));
                    validForPublishing = false;
                }

                //Publish and then update the database with new status
                bool published = validForPublishing && _publishingStrategy.Publish(content, userId);

                var uow = _uowProvider.GetUnitOfWork();
                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
                    content.WriterId = userId;

                    repository.AddOrUpdate(content);

                    uow.Commit();

                    var xml = content.ToXml();
                    //Preview Xml
                    var previewPoco = new PreviewXmlDto
                        {
                            NodeId = content.Id,
                            Timestamp = DateTime.Now,
                            VersionId = content.Version,
                            Xml = xml.ToString(SaveOptions.None)
                        };
                    var previewExists =
                        uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
                                                        new { Id = content.Id, Version = content.Version }) != 0;
                    int previewResult = previewExists
                                            ? uow.Database.Update<PreviewXmlDto>(
                                                "SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
                                                new
                                                    {
                                                        Xml = previewPoco.Xml,
                                                        Timestamp = previewPoco.Timestamp,
                                                        Id = previewPoco.NodeId,
                                                        Version = previewPoco.VersionId
                                                    })
                                            : Convert.ToInt32(uow.Database.Insert(previewPoco));

                    if (published)
                    {
                        //Content Xml
                        var contentPoco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) };
                        var contentExists = uow.Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
                        int contentResult = contentExists
                                                ? uow.Database.Update(contentPoco)
                                                : Convert.ToInt32(uow.Database.Insert(contentPoco));

                    }
                }

                if (raiseEvents)
                    Saved.RaiseEvent(new SaveEventArgs<IContent>(content, false), this);

                //Save xml to db and call following method to fire event through PublishingStrategy to update cache
                if (published && omitCacheRefresh == false)
                    _publishingStrategy.PublishingFinalized(content);

                //We need to check if children and their publish state to ensure that we 'republish' content that was previously published
                if (published && omitCacheRefresh == false && previouslyPublished == false && HasChildren(content.Id))
                {
                    var descendants = GetPublishedDescendants(content);

                    _publishingStrategy.PublishingFinalized(descendants, false);
                }

                Audit.Add(AuditTypes.Publish, "Save and Publish performed by user", userId, content.Id);

                return published;
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Publishes a <see cref="IContent"/> object and all its children
        /// </summary>
        /// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
        /// <param name="omitCacheRefresh">Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will update the cache.</param>
        /// <param name="userId">Optional Id of the User issueing the publishing</param>
        /// <returns>True if publishing succeeded, otherwise False</returns>
        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)
            {
                LogHelper.Info<ContentService>(
                    string.Format(
                        "Content '{0}' with Id '{1}' could not be published because its parent or one of its ancestors 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<ContentService>(
                    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<IContent>.Builder.Where(x => x.Path.StartsWith(content.Path));

            var updated = new List<IContent>();
            var list = new List<IContent>();
            list.Add(content);
            list.AddRange(GetDescendants(content));

            //Publish and then update the database with new status
            var published = _publishingStrategy.PublishWithChildren(list, userId);
            if (published)
            {
                var uow = _uowProvider.GetUnitOfWork();
                using (var repository = _repositoryFactory.CreateContentRepository(uow))
                {
                    //Only loop through content where the Published property has been updated
                    foreach (var item in list.Where(x => ((ICanBeDirty)x).IsPropertyDirty("Published")))
                    {
                        item.WriterId = userId;
                        repository.AddOrUpdate(item);
                        updated.Add(item);
                    }

                    uow.Commit();

                    foreach (var c in updated)
                    {
                        var xml = c.ToXml();
                        var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
                        var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = c.Id }) !=
                                     null;
                        int result = exists
                                         ? uow.Database.Update(poco)
                                         : Convert.ToInt32(uow.Database.Insert(poco));
                    }
                }
                //Save xml to db and call following method to fire event:
                if (omitCacheRefresh == false)
                    _publishingStrategy.PublishingFinalized(updated, false);

                Audit.Add(AuditTypes.Publish, "Publish with Children performed by user", userId, content.Id);
            }

            return published;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Rebuilds all xml content in the cmsContentXml table for all published documents
        /// </summary>
        /// <returns>True if publishing succeeded, otherwise False</returns>
        private void RePublishAllDo(params int[] contentTypeIds)
        {
            using (new WriteLock(Locker))
            {
                var list = new List<IContent>();

                var uow = _uowProvider.GetUnitOfWork();
                using (var repository = _repositoryFactory.CreateContentRepository(uow))
                {
                    if (!contentTypeIds.Any())
                    {
                        //since we're updating all records, it will be much faster to just clear the table first
                        uow.Database.TruncateTable("cmsContentXml");

                        //get all content items that are published
                        //  Consider creating a Path query instead of recursive method:
                        //  var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith("-1"));
                        var rootContent = GetRootContent();
                        foreach (var content in rootContent.Where(content => content.Published))
                        {
                            list.Add(content);
                            list.AddRange(GetPublishedDescendants(content));
                        }
                    }
                    else
                    {
                        foreach (var id in contentTypeIds)
                        {
                            //first we'll clear out the data from the cmsContentXml table for this type
                            uow.Database.Execute(@"delete from cmsContentXml where nodeId in 
(select cmsDocument.nodeId from cmsDocument 
	inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
	where published = 1 and contentType = @contentTypeId)", new { contentTypeId = id });

                            //now get all published content objects of this type and add to the list
                            list.AddRange(GetContentOfContentType(id).Where(content => content.Published));
                        }
                    }

                    foreach (var c in list)
                    {
                        //generate the xml
                        var xml = c.ToXml();
                        //create the dto to insert
                        var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
                        //insert it into the database
                        uow.Database.Insert(poco);
                    }
                }

                Audit.Add(AuditTypes.Publish, "RePublish All completed, the xml has been regenerated in the database", 0, -1);
            }
        }
Ejemplo n.º 8
0
	    /// <summary>
	    /// Saves a single <see cref="IMedia"/> object
	    /// </summary>
	    /// <param name="media">The <see cref="IMedia"/> to save</param>
	    /// <param name="userId">Id of the User saving the Content</param>
        /// <param name="raiseEvents">Optional boolean indicating whether or not to raise events.</param>
        public void Save(IMedia media, int userId = 0, bool raiseEvents = true)
	    {
            if(raiseEvents)
			{
                if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMedia>(media), this))
				return;
            }

	        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));
	            }

	            if (raiseEvents)
	                Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);

	            Audit.Add(AuditTypes.Save, "Save Media performed by user", media.CreatorId, media.Id);
	        }
	    }