Esempio n. 1
0
        /// <summary>
        /// Saves the given page model
        /// </summary>
        /// <param name="model">The page model</param>
        /// <param name="isDraft">If the model should be saved as a draft</param>
        private async Task <IEnumerable <Guid> > Save <T>(T model, bool isDraft) where T : PageBase
        {
            return(await InTx(async session =>
            {
                var backThen = new DateTime(2020, 1, 1, 0, 0, 0);
                var revisionNumber = (DateTime.Now - backThen).TotalMilliseconds;

                var type = App.PageTypes.GetById(model.TypeId);
                var affected = new List <Guid>();
                var isNew = false;
                var lastModified = DateTime.MinValue;

                if (type == null)
                {
                    return affected;
                }
                var page = await session.GetAsync <PageEntity>(model.Id).ConfigureAwait(false);
                //  IQueryable<Page> pageQuery = _db.Pages;
                //  if (isDraft)
                //  {
                //      pageQuery = pageQuery.AsNoTracking();
                //  }

                //  var page = await pageQuery
                //      .Include(p => p.Permissions)
                //      .Include(p => p.Blocks).ThenInclude(b => b.Block).ThenInclude(b => b.Fields)
                //      .Include(p => p.Fields)
                //      .FirstOrDefaultAsync(p => p.Id == model.Id)
                //      .ConfigureAwait(false);

                if (page == null)
                {
                    isNew = true;
                }
                else
                {
                    lastModified = page.LastModified;
                }

                if (model.OriginalPageId.HasValue)
                {
                    var originalPage = await session.Query <PageEntity>().FirstOrDefaultAsync(p => p.Id == model.OriginalPageId).ConfigureAwait(false);
                    //var originalPage = (await _db.Pages.AsNoTracking().FirstOrDefaultAsync(p => p.Id == model.OriginalPageId).ConfigureAwait(false));
                    var originalPageIsCopy = originalPage?.OriginalPageId.HasValue ?? false;
                    if (originalPageIsCopy)
                    {
                        throw new InvalidOperationException("Can not set copy of a copy");
                    }

                    var originalPageType = originalPage?.PageType.Id;
                    if (originalPageType != model.TypeId)
                    {
                        throw new InvalidOperationException("Copy can not have a different content type");
                    }

                    // Transform the model
                    if (page == null)
                    {
                        page = new PageEntity()
                        {
                            //Id = model.Id != Guid.Empty ? model.Id : Guid.NewGuid(),
                            Created = DateTime.Now,
                        };

                        if (!isDraft)
                        {
                            await session.SaveAsync(page).ConfigureAwait(false);
                            //await _db.Pages.AddAsync(page).ConfigureAwait(false);

                            // Make room for the new page
                            var dest = await session.Query <PageEntity>().Where(p => p.Site.Id == model.SiteId && p.Parent.Id == model.ParentId).ToListAsync().ConfigureAwait(false);
                            //var dest = await _db.Pages.Where(p => p.SiteId == model.SiteId && p.ParentId == model.ParentId).ToListAsync().ConfigureAwait(false);
                            affected.AddRange(MovePages(dest, page.Id, model.SiteId, model.SortOrder, true));
                        }
                    }
                    else
                    {
                        // Check if the page has been moved
                        if (!isDraft && (page.Parent.Id != model.ParentId || page.SortOrder != model.SortOrder))
                        {
                            var source = await session.Query <PageEntity>().Where(p => p.Site == page.Site && p.Parent == page.Parent && p.Id != model.Id).ToListAsync().ConfigureAwait(false);
                            //var source = await _db.Pages.Where(p => p.SiteId == page.SiteId && p.ParentId == page.ParentId && p.Id != model.Id).ToListAsync().ConfigureAwait(false);
                            var dest = page.Parent.Id == model.ParentId ? source : await session.Query <PageEntity>().Where(p => p.Site.Id == model.SiteId && p.Parent.Id == model.ParentId).ToListAsync().ConfigureAwait(false);
                            //var dest = page.Parent.Id == model.ParentId ? source : await _db.Pages.Where(p => p.SiteId == model.SiteId && p.ParentId == model.ParentId).ToListAsync().ConfigureAwait(false);

                            // Remove the old position for the page
                            affected.AddRange(MovePages(source, page.Id, page.Site.Id, page.SortOrder + 1, false));
                            // Add room for the new position of the page
                            affected.AddRange(MovePages(dest, page.Id, model.SiteId, model.SortOrder, true));
                        }
                    }

                    if (!isDraft && (isNew || page.Title != model.Title || page.NavigationTitle != model.NavigationTitle))
                    {
                        // If this is new page or title has been updated it means
                        // the global sitemap changes. Notify the service.
                        affected.Add(page.Id);
                    }

                    page.ContentType = type.IsArchive ? "Blog" : "Page";
                    page.PageType = await session.GetAsync <PageTypeEntity>(model.TypeId).ConfigureAwait(false);
                    //page.PageTypeId = model.TypeId;
                    page.OriginalPageId = model.OriginalPageId;
                    page.Site = await session.GetAsync <SiteEntity>(model.SiteId).ConfigureAwait(false);
                    //page.SiteId = model.SiteId;
                    page.Title = model.Title;
                    page.NavigationTitle = model.NavigationTitle;
                    page.Slug = model.Slug;
                    page.Parent = await session.GetAsync <PageEntity>(model.ParentId).ConfigureAwait(false);
                    //page.ParentId = model.ParentId;
                    page.SortOrder = model.SortOrder;
                    page.IsHidden = model.IsHidden;
                    page.Route = model.Route;
                    page.Published = model.Published;
                    page.RevisionNumber = revisionNumber;
                    //page.LastModified = DateTime.Now;

                    page.Permissions.Clear();
                    foreach (var permission in model.Permissions)
                    {
                        page.Permissions.Add(new PagePermissionEntity
                        {
                            PageId = page.Id,
                            Permission = permission
                        });
                    }

                    if (!isDraft)
                    {
                        // NHibernate tracks changes automatically and writes on commit
                        //await _db.SaveChangesAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        await MakeDraft(session, model, revisionNumber, lastModified, page).ConfigureAwait(false);
                        // model.Id = await MakeDraft(session, page, revisionNumber, lastModified).ConfigureAwait(false);
                        model.Id = page.Id;
                    }
                    return affected;
                }

                // Transform the model
                if (page == null)
                {
                    page = new PageEntity
                    {
                        //Id = model.Id != Guid.Empty ? model.Id : Guid.NewGuid(),
                        Parent = (model.ParentId != null && model.ParentId != Guid.Empty) ? await session.GetAsync <PageEntity>(model.ParentId).ConfigureAwait(false) : null,
                        //ParentId = model.ParentId,
                        SortOrder = model.SortOrder,
                        PageType = await session.GetAsync <PageTypeEntity>(model.TypeId).ConfigureAwait(false),
                        //PageTypeId = model.TypeId,
                        //Created = DateTime.Now,
                        RevisionNumber = revisionNumber,
                        //LastModified = DateTime.Now,
                        // ### Begin RT changes ###
                        Title = model.Title,
                        Site = await session.GetAsync <SiteEntity>(model.SiteId).ConfigureAwait(false),
                        ContentType = type.IsArchive ? "Blog" : "Page"
                                      // ### End RT changes #####
                    };

                    if (!isDraft)
                    {
                        await session.SaveAsync(page).ConfigureAwait(false);
                        model.Id = page.Id; // Only after the new entity object has been saved to NHibernate
                        var dest = await session.Query <PageEntity>().Where(p => p.Site != null && p.Parent != null && p.Site.Id == model.SiteId && p.Parent.Id == model.ParentId).ToListAsync().ConfigureAwait(false);
                        //var dest = await _db.Pages.Where(p => p.SiteId == model.SiteId && p.ParentId == model.ParentId).ToListAsync().ConfigureAwait(false);
                        affected.AddRange(MovePages(dest, page.Id, model.SiteId, model.SortOrder, true));
                    }
                }
                else
                {
                    // ### Begin RT changes ###
                    page.Parent = (model.ParentId != null && model.ParentId != Guid.Empty) ? await session.GetAsync <PageEntity>(model.ParentId).ConfigureAwait(false) : null;
                    // ### End RT changes #####
                    // Check if the page has been moved
                    if (page.Parent != null && !isDraft && (page.Parent.Id != model.ParentId || page.SortOrder != model.SortOrder))
                    {
                        // ### Begin RT changes ###
                        // var siteId = $"Site id = '{page.Site.Id}'";
                        // var isPageParentNull = $"Page parent is null '{page.Parent == null}'";
                        // var parentId = $"Parent id = '{page.Parent.Id}'";
                        // ### End RT changes #####
                        var source = await session.Query <PageEntity>().Where(p => p.Site == page.Site && p.Parent == page.Parent && p.Id != model.Id).ToListAsync().ConfigureAwait(false);
                        //var source = await _db.Pages.Where(p => p.SiteId == page.SiteId && p.ParentId == page.Parent.Id && p.Id != model.Id).ToListAsync().ConfigureAwait(false);
                        var dest = page.Parent.Id == model.ParentId ? source : await session.Query <PageEntity>().Where(p => p.Site.Id == model.SiteId && p.Parent != null && p.Parent.Id == model.ParentId).ToListAsync().ConfigureAwait(false);
                        //var dest = page.Parent.Id == model.ParentId ? source : await _db.Pages.Where(p => p.SiteId == model.SiteId && p.ParentId == model.ParentId).ToListAsync().ConfigureAwait(false);

                        // Remove the old position for the page
                        affected.AddRange(MovePages(source, page.Id, page.Site.Id, page.SortOrder + 1, false));
                        // Add room for the new position of the page
                        affected.AddRange(MovePages(dest, page.Id, model.SiteId, model.SortOrder, true));
                    }
                    page.LastModified = DateTime.Now;
                }

                if (isNew || page.Title != model.Title || page.NavigationTitle != model.NavigationTitle)
                {
                    // If this is new page or title has been updated it means
                    // the global sitemap changes. Notify the service.
                    affected.Add(page.Id);
                }

                page = _contentService.Transform(model, type, page);
                page.ContentType = type.IsArchive ? "Blog" : "Page";

                // Set if comments should be enabled
                page.EnableComments = model.EnableComments;
                page.CloseCommentsAfterDays = model.CloseCommentsAfterDays;

                // Update permissions
                page.Permissions.Clear();
                foreach (var permission in model.Permissions)
                {
                    page.Permissions.Add(new PagePermissionEntity
                    {
                        PageId = page.Id,
                        Permission = permission
                    });
                }

                // Make sure foreign key is set for fields
                if (!isDraft)
                {
                    foreach (var field in page.Fields)
                    {
                        if (field.Page == null)
                        //if (field.PageId == Guid.Empty)
                        {
                            field.Page = page;
                            //field.PageId = page.Id;
                            await session.SaveOrUpdateAsync(field).ConfigureAwait(false);
                            //await _db.PageFields.AddAsync(field).ConfigureAwait(false);
                        }
                    }
                }

                // Transform blocks
                var blockModels = model.Blocks;

                if (blockModels != null)
                {
                    var blocks = _contentService.TransformBlocks(blockModels, session);

                    var current = blocks.Select(b => b.Id).ToArray();

                    // Delete removed blocks
                    var removed = page.Blocks
                                  .Where(b => !current.Contains(b.Block.Id) && !b.Block.IsReusable && b.Block.ParentId == null)
                                  .Select(b => b.Block);
                    var removedItems = page.Blocks
                                       .Where(b => !current.Contains(b.Block.Id) && b.Block.ParentId != null && removed.Select(p => p.Id).ToList().Contains(b.Block.ParentId.Value))
                                       .Select(b => b.Block);

                    if (!isDraft)
                    {
                        foreach (var block in removed)
                        {
                            await session.DeleteAsync(block).ConfigureAwait(false);
                        }
                        //_db.Blocks.RemoveRange(removed);
                        foreach (var block in removedItems)
                        {
                            await session.DeleteAsync(block).ConfigureAwait(false);
                        }
                        //_db.Blocks.RemoveRange(removedItems);
                    }

                    // Delete the old page blocks
                    page.Blocks.Clear();

                    // Now map the new block
                    for (var n = 0; n < blocks.Count; n++)
                    {
                        var block = await session.GetAsync <BlockEntity>(blocks[n].Id).ConfigureAwait(false);
                        //var block = await session.Query<BlockEntity>().FirstOrDefaultAsync(b => b.Id == blocks[n].Id).ConfigureAwait(false);
                        // IQueryable<BlockEntity> blockQuery = _db.Blocks;
                        // if (isDraft)
                        // {
                        //     blockQuery = blockQuery.AsNoTracking();
                        // }

                        // var block = await blockQuery
                        //     .Include(b => b.Fields)
                        //     .FirstOrDefaultAsync(b => b.Id == blocks[n].Id)
                        //     .ConfigureAwait(false);

                        if (block == null)
                        {
                            block = new BlockEntity
                            {
                                //Id = blocks[n].Id != Guid.Empty ? blocks[n].Id : Guid.NewGuid(),
                                Created = DateTime.Now
                            };
                            if (!isDraft)
                            {
                                session.Save(block);
                            }
                        }
                        block.ParentId = blocks[n].ParentId;
                        block.CLRType = blocks[n].CLRType;
                        block.IsReusable = blocks[n].IsReusable;
                        block.Title = blocks[n].Title;
                        block.LastModified = DateTime.Now;

                        session.Flush();

                        var currentFields = blocks[n].Fields.Select(f => f.FieldId).Distinct();
                        var removedFields = block.Fields.Where(f => !currentFields.Contains(f.FieldId));

                        if (!isDraft)
                        {
                            foreach (var field in removedFields)
                            {
                                await session.DeleteAsync(field).ConfigureAwait(false);
                            }
                            //_db.BlockFields.RemoveRange(removedFields);
                        }

                        foreach (var newField in blocks[n].Fields)
                        {
                            var field = block.Fields.FirstOrDefault(f => f.FieldId == newField.FieldId);
                            if (field == null)
                            {
                                field = new BlockFieldEntity
                                {
                                    //Id = newField.Id != Guid.Empty ? newField.Id : Guid.NewGuid(),
                                    Block = block,
                                    //BlockId = block.Id,
                                    FieldId = newField.FieldId
                                              //CLRType = newField.CLRType
                                };
                                if (!isDraft)
                                {
                                    //await session.SaveAsync(field).ConfigureAwait(false);
                                    //await _db.BlockFields.AddAsync(field).ConfigureAwait(false);
                                }
                                block.Fields.Add(field);
                            }
                            field.SortOrder = newField.SortOrder;
                            field.CLRType = newField.CLRType;
                            field.Value = newField.Value;
                            if (!isDraft)
                            {
                                await session.SaveOrUpdateAsync(field).ConfigureAwait(false);
                            }
                        }

                        // Create the page block
                        var pageBlock = new PageBlockEntity
                        {
                            //Id = Guid.NewGuid(),
                            Block = block,
                            //BlockId = block.Id,
                            Page = page,
                            //PageId = page.Id,
                            SortOrder = n
                        };
                        if (!isDraft)
                        {
                            await session.SaveAsync(pageBlock).ConfigureAwait(false);
                            //await _db.PageBlocks.AddAsync(pageBlock).ConfigureAwait(false);
                        }
                        page.Blocks.Add(pageBlock);
                    }
                }
                if (!isDraft)
                {
                    // NHibernate keeps track of changes and writes as needed.
                    //await _db.SaveChangesAsync().ConfigureAwait(false);
                }
                else
                {
                    await MakeDraft(session, model, revisionNumber, lastModified, page).ConfigureAwait(false);
                    model.Id = page.Id;
                    // model.Id = await MakeDraft(session, page, revisionNumber, lastModified).ConfigureAwait(false);
                }
                return affected;
            }).ConfigureAwait(false));
        }
Esempio n. 2
0
        /// <summary>
        /// Transforms the given blocks to the internal data model.
        /// </summary>
        /// <param name="models">The blocks</param>
        /// <returns>The data model</returns>
        public IList <BlockEntity> TransformBlocks(IList <Block> models, ISession session)
        {
            var blocks = new List <BlockEntity>();

            if (models != null)
            {
                for (var n = 0; n < models.Count; n++)
                {
                    var type = App.Blocks.GetByType(models[n].GetType().FullName);

                    if (type != null)
                    {
                        BlockEntity block = session.Get <BlockEntity>(models[n].Id) ?? new BlockEntity();
                        block.CLRType      = models[n].GetType().FullName;
                        block.Created      = DateTime.Now;
                        block.LastModified = DateTime.Now;
                        // block = new BlockEntity()
                        // {
                        //    //Id = models[n].Id != Guid.Empty ? models[n].Id : Guid.NewGuid(),
                        //    CLRType = models[n].GetType().FullName,
                        //    Created = DateTime.Now,
                        //    LastModified = DateTime.Now
                        // };
                        session.SaveOrUpdate(block);

                        foreach (var prop in models[n].GetType().GetProperties(App.PropertyBindings))
                        {
                            if (typeof(IField).IsAssignableFrom(prop.PropertyType))
                            {
                                // Only save fields to the database
                                var field = new BlockFieldEntity()
                                {
                                    //Id = Guid.NewGuid(),
                                    Block = block,
                                    //BlockId = block.Id,
                                    FieldId   = prop.Name,
                                    SortOrder = 0,
                                    CLRType   = prop.PropertyType.FullName,
                                    Value     = App.SerializeObject(prop.GetValue(models[n]), prop.PropertyType)
                                };
                                session.SaveOrUpdate(field);
                                block.Fields.Add(field);
                            }
                        }
                        blocks.Add(block);

                        if (typeof(BlockGroup).IsAssignableFrom(models[n].GetType()))
                        {
                            var blockItems = TransformBlocks(((BlockGroup)models[n]).Items, session);

                            if (blockItems.Count > 0)
                            {
                                foreach (var item in blockItems)
                                {
                                    item.ParentId = block.Id;
                                }
                                blocks.AddRange(blockItems);
                            }
                        }
                    }
                }
            }
            return(blocks);
        }