Example #1
0
        /// <summary>
        /// Transforms the given blocks to the internal data model.
        /// </summary>
        /// <param name="models">The blocks</param>
        /// <param name="languageId">The language id</param>
        /// <returns>The data model</returns>
        public IList <ContentBlock> TransformContentBlocks(IList <Extend.Block> models, Guid languageId)
        {
            var blocks = new List <ContentBlock>();

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

                    if (type != null)
                    {
                        // Make sure we generate an id if it's empty
                        if (models[n].Id == Guid.Empty)
                        {
                            models[n].Id = Guid.NewGuid();
                        }

                        var block = new ContentBlock()
                        {
                            Id      = models[n].Id,
                            CLRType = models[n].GetType().FullName
                        };

                        foreach (var prop in models[n].GetType().GetProperties(App.PropertyBindings))
                        {
                            if (typeof(Extend.IField).IsAssignableFrom(prop.PropertyType))
                            {
                                var blockValue = prop.GetValue(models[n]);

                                // Only save fields to the database
                                var field = new ContentBlockField()
                                {
                                    Id        = Guid.NewGuid(),
                                    BlockId   = block.Id,
                                    FieldId   = prop.Name,
                                    SortOrder = 0,
                                    CLRType   = prop.PropertyType.FullName,
                                };

                                // Set value
                                if (blockValue is Extend.ITranslatable)
                                {
                                    var translation = new ContentBlockFieldTranslation
                                    {
                                        FieldId    = field.Id,
                                        LanguageId = languageId,
                                        Value      = App.SerializeObject(blockValue, prop.PropertyType)
                                    };
                                    field.Translations.Add(translation);
                                }
                                else
                                {
                                    field.Value = App.SerializeObject(blockValue, prop.PropertyType);
                                }
                                block.Fields.Add(field);
                            }
                        }
                        blocks.Add(block);

                        if (typeof(Extend.BlockGroup).IsAssignableFrom(models[n].GetType()))
                        {
                            var blockItems = TransformContentBlocks(((Extend.BlockGroup)models[n]).Items, languageId);

                            if (blockItems.Count() > 0)
                            {
                                foreach (var item in blockItems)
                                {
                                    item.ParentId = block.Id;
                                }
                                blocks.AddRange(blockItems);
                            }
                        }
                    }
                }
            }
            return(blocks);
        }
Example #2
0
        /// <summary>
        /// Saves the given content model
        /// </summary>
        /// <param name="model">The content model</param>
        /// <param name="languageId">The selected language id</param>
        public async Task Save <T>(T model, Guid languageId) where T : Models.GenericContent
        {
            var type         = App.ContentTypes.GetById(model.TypeId);
            var lastModified = DateTime.MinValue;

            if (type != null)
            {
                // Ensure category
                if (type.UseCategory)
                {
                    if (model is Models.ICategorizedContent categorized)
                    {
                        var category = await _db.Taxonomies
                                       .FirstOrDefaultAsync(c => c.Id == categorized.Category.Id)
                                       .ConfigureAwait(false);

                        if (category == null)
                        {
                            if (!string.IsNullOrWhiteSpace(categorized.Category.Slug))
                            {
                                category = await _db.Taxonomies
                                           .FirstOrDefaultAsync(c => c.GroupId == type.Group && c.Slug == categorized.Category.Slug && c.Type == TaxonomyType.Category)
                                           .ConfigureAwait(false);
                            }
                            if (category == null && !string.IsNullOrWhiteSpace(categorized.Category.Title))
                            {
                                category = await _db.Taxonomies
                                           .FirstOrDefaultAsync(c => c.GroupId == type.Group && c.Title == categorized.Category.Title && c.Type == TaxonomyType.Category)
                                           .ConfigureAwait(false);
                            }

                            if (category == null)
                            {
                                category = new Taxonomy
                                {
                                    Id           = categorized.Category.Id != Guid.Empty ? categorized.Category.Id : Guid.NewGuid(),
                                    GroupId      = type.Group,
                                    Type         = TaxonomyType.Category,
                                    Title        = categorized.Category.Title,
                                    Slug         = Utils.GenerateSlug(categorized.Category.Title),
                                    Created      = DateTime.Now,
                                    LastModified = DateTime.Now
                                };
                                await _db.Taxonomies.AddAsync(category).ConfigureAwait(false);
                            }
                            categorized.Category.Id    = category.Id;
                            categorized.Category.Title = category.Title;
                            categorized.Category.Slug  = category.Slug;
                        }
                    }
                }

                // Ensure tags
                if (type.UseTags)
                {
                    if (model is Models.ITaggedContent tagged)
                    {
                        foreach (var t in tagged.Tags)
                        {
                            var tag = await _db.Taxonomies
                                      .FirstOrDefaultAsync(tg => tg.Id == t.Id)
                                      .ConfigureAwait(false);

                            if (tag == null)
                            {
                                if (!string.IsNullOrWhiteSpace(t.Slug))
                                {
                                    tag = await _db.Taxonomies
                                          .FirstOrDefaultAsync(tg => tg.GroupId == type.Group && tg.Slug == t.Slug && tg.Type == TaxonomyType.Tag)
                                          .ConfigureAwait(false);
                                }
                                if (tag == null && !string.IsNullOrWhiteSpace(t.Title))
                                {
                                    tag = await _db.Taxonomies
                                          .FirstOrDefaultAsync(tg => tg.GroupId == type.Group && tg.Title == t.Title && tg.Type == TaxonomyType.Tag)
                                          .ConfigureAwait(false);
                                }

                                if (tag == null)
                                {
                                    tag = new Taxonomy
                                    {
                                        Id           = t.Id != Guid.Empty ? t.Id : Guid.NewGuid(),
                                        GroupId      = type.Group,
                                        Type         = TaxonomyType.Tag,
                                        Title        = t.Title,
                                        Slug         = Utils.GenerateSlug(t.Title),
                                        Created      = DateTime.Now,
                                        LastModified = DateTime.Now
                                    };
                                    await _db.Taxonomies.AddAsync(tag).ConfigureAwait(false);
                                }
                                t.Id = tag.Id;
                            }
                            t.Title = tag.Title;
                            t.Slug  = tag.Slug;
                        }
                    }
                }

                var content = await _db.Content
                              .Include(c => c.Translations)
                              .Include(c => c.Blocks).ThenInclude(b => b.Fields).ThenInclude(f => f.Translations)
                              .Include(c => c.Fields).ThenInclude(f => f.Translations)
                              .Include(c => c.Category)
                              .Include(c => c.Tags).ThenInclude(t => t.Taxonomy)
                              .AsSplitQuery()
                              .FirstOrDefaultAsync(p => p.Id == model.Id)
                              .ConfigureAwait(false);

                // If not, create new content
                if (content == null)
                {
                    content = new Content
                    {
                        Id           = model.Id != Guid.Empty ? model.Id : Guid.NewGuid(),
                        Created      = DateTime.Now,
                        LastModified = DateTime.Now
                    };
                    model.Id = content.Id;

                    await _db.Content.AddAsync(content).ConfigureAwait(false);
                }
                else
                {
                    content.LastModified = DateTime.Now;
                }
                content = _service.Transform <T>(model, type, content, languageId);

                // Process fields
                foreach (var field in content.Fields)
                {
                    // Ensure foreign key for new fields
                    if (field.ContentId == Guid.Empty)
                    {
                        field.ContentId = content.Id;
                        await _db.ContentFields.AddAsync(field).ConfigureAwait(false);
                    }
                }

                if (type.UseTags)
                {
                    if (model is Models.ITaggedContent taggedModel)
                    {
                        // Remove tags
                        var removedTags = new List <ContentTaxonomy>();
                        foreach (var tag in content.Tags)
                        {
                            if (!taggedModel.Tags.Any(t => t.Id == tag.TaxonomyId))
                            {
                                removedTags.Add(tag);
                            }
                        }
                        foreach (var removed in removedTags)
                        {
                            content.Tags.Remove(removed);
                        }

                        // Add tags
                        foreach (var tag in taggedModel.Tags)
                        {
                            if (!content.Tags.Any(t => t.ContentId == content.Id && t.TaxonomyId == tag.Id))
                            {
                                var contentTaxonomy = new ContentTaxonomy
                                {
                                    ContentId  = content.Id,
                                    TaxonomyId = tag.Id
                                };
                                content.Tags.Add(contentTaxonomy);
                            }
                        }
                    }
                }

                // Transform blocks
                if (model is Models.IBlockContent blockModel)
                {
                    var blockModels = blockModel.Blocks;

                    if (blockModels != null)
                    {
                        var blocks  = _service.TransformContentBlocks(blockModels, languageId);
                        var current = blocks.Select(b => b.Id).ToArray();

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

                        _db.ContentBlocks.RemoveRange(removed);
                        _db.ContentBlocks.RemoveRange(removedItems);

                        // Map the new block
                        for (var n = 0; n < blocks.Count; n++)
                        {
                            var block = content.Blocks.FirstOrDefault(b => b.Id == blocks[n].Id);

                            if (block == null)
                            {
                                block = new ContentBlock
                                {
                                    Id = blocks[n].Id != Guid.Empty ? blocks[n].Id : Guid.NewGuid()
                                };
                                await _db.ContentBlocks.AddAsync(block).ConfigureAwait(false);
                            }
                            block.ParentId  = blocks[n].ParentId;
                            block.SortOrder = n;
                            block.CLRType   = blocks[n].CLRType;

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

                            _db.ContentBlockFields.RemoveRange(removedFields);

                            foreach (var newField in blocks[n].Fields)
                            {
                                var field = block.Fields.FirstOrDefault(f => f.FieldId == newField.FieldId);
                                if (field == null)
                                {
                                    field = new ContentBlockField
                                    {
                                        Id      = newField.Id != Guid.Empty ? newField.Id : Guid.NewGuid(),
                                        BlockId = block.Id,
                                        FieldId = newField.FieldId
                                    };
                                    await _db.ContentBlockFields.AddAsync(field).ConfigureAwait(false);

                                    block.Fields.Add(field);
                                }
                                field.SortOrder = newField.SortOrder;
                                field.CLRType   = newField.CLRType;
                                field.Value     = newField.Value;

                                foreach (var newTranslation in newField.Translations)
                                {
                                    var translation = field.Translations.FirstOrDefault(t => t.LanguageId == newTranslation.LanguageId);
                                    if (translation == null)
                                    {
                                        translation = new ContentBlockFieldTranslation
                                        {
                                            FieldId    = field.Id,
                                            LanguageId = languageId
                                        };
                                        await _db.ContentBlockFieldTranslations.AddAsync(translation).ConfigureAwait(false);

                                        field.Translations.Add(translation);
                                    }
                                    translation.Value = newTranslation.Value;
                                }
                            }
                            content.Blocks.Add(block);
                        }
                    }
                }

                await _db.SaveChangesAsync().ConfigureAwait(false);

                /*
                 * TODO
                 *
                 * await DeleteUnusedCategories(model.BlogId).ConfigureAwait(false);
                 * await DeleteUnusedTags(model.BlogId).ConfigureAwait(false);
                 */
            }
        }