Ejemplo n.º 1
0
        private void UpdateBlockListRecursively(BlockEditorData blockListData, Func <Guid> createGuid)
        {
            var oldToNew = new Dictionary <Udi, Udi>();

            MapOldToNewUdis(oldToNew, blockListData.BlockValue.ContentData, createGuid);
            MapOldToNewUdis(oldToNew, blockListData.BlockValue.SettingsData, createGuid);

            for (var i = 0; i < blockListData.References.Count; i++)
            {
                var reference      = blockListData.References[i];
                var hasContentMap  = oldToNew.TryGetValue(reference.ContentUdi, out var contentMap);
                Udi settingsMap    = null;
                var hasSettingsMap = reference.SettingsUdi != null && oldToNew.TryGetValue(reference.SettingsUdi, out settingsMap);

                if (hasContentMap)
                {
                    // replace the reference
                    blockListData.References.RemoveAt(i);
                    blockListData.References.Insert(i, new ContentAndSettingsReference(contentMap, hasSettingsMap ? settingsMap : null));
                }
            }

            // build the layout with the new UDIs
            var layout = (JArray)blockListData.Layout;

            layout.Clear();
            foreach (var reference in blockListData.References)
            {
                layout.Add(JObject.FromObject(new BlockListLayoutItem
                {
                    ContentUdi  = reference.ContentUdi,
                    SettingsUdi = reference.SettingsUdi
                }));
            }


            RecursePropertyValues(blockListData.BlockValue.ContentData, createGuid);
            RecursePropertyValues(blockListData.BlockValue.SettingsData, createGuid);
        }
        public BlockEditorData?DeserializeAndClean(object?propertyValue)
        {
            if (propertyValue == null || string.IsNullOrWhiteSpace(propertyValue.ToString()))
            {
                return(null);
            }

            BlockEditorData blockEditorData = _dataConverter.Deserialize(propertyValue.ToString() !);

            if (blockEditorData.BlockValue.ContentData.Count == 0)
            {
                // if there's no content ensure there's no settings too
                blockEditorData.BlockValue.SettingsData.Clear();
                return(null);
            }

            var contentTypePropertyTypes = new Dictionary <string, Dictionary <string, IPropertyType> >();

            // filter out any content that isn't referenced in the layout references
            foreach (BlockItemData block in blockEditorData.BlockValue.ContentData.Where(x =>
                                                                                         blockEditorData.References.Any(r => x.Udi is not null && r.ContentUdi == x.Udi)))
            {
                ResolveBlockItemData(block, contentTypePropertyTypes);
            }

            // filter out any settings that isn't referenced in the layout references
            foreach (BlockItemData block in blockEditorData.BlockValue.SettingsData.Where(x =>
                                                                                          blockEditorData.References.Any(r =>
                                                                                                                         r.SettingsUdi is not null && x.Udi is not null && r.SettingsUdi == x.Udi)))
            {
                ResolveBlockItemData(block, contentTypePropertyTypes);
            }

            // remove blocks that couldn't be resolved
            blockEditorData.BlockValue.ContentData.RemoveAll(x => x.ContentTypeAlias.IsNullOrWhiteSpace());
            blockEditorData.BlockValue.SettingsData.RemoveAll(x => x.ContentTypeAlias.IsNullOrWhiteSpace());

            return(blockEditorData);
        }
Ejemplo n.º 3
0
    /// <inheritdoc />
    public override object?ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object?inter, bool preview)
    {
        // NOTE: The intermediate object is just a JSON string, we don't actually convert from source -> intermediate since source is always just a JSON string
        using (_proflog.DebugDuration <BlockListPropertyValueConverter>(
                   $"ConvertPropertyToBlockList ({propertyType.DataType.Id})"))
        {
            var value = (string?)inter;

            // Short-circuit on empty values
            if (string.IsNullOrWhiteSpace(value))
            {
                return(BlockListModel.Empty);
            }

            BlockEditorData converted = _blockListEditorDataConverter.Deserialize(value);
            if (converted.BlockValue.ContentData.Count == 0)
            {
                return(BlockListModel.Empty);
            }

            IEnumerable <BlockListLayoutItem>?blockListLayout =
                converted.Layout?.ToObject <IEnumerable <BlockListLayoutItem> >();
            if (blockListLayout is null)
            {
                return(BlockListModel.Empty);
            }

            // Get configuration
            BlockListConfiguration?configuration = propertyType.DataType.ConfigurationAs <BlockListConfiguration>();
            if (configuration is null)
            {
                return(null);
            }

            var blockConfigMap = configuration.Blocks.ToDictionary(x => x.ContentElementTypeKey);

            // Convert the content data
            var contentPublishedElements = new Dictionary <Guid, IPublishedElement>();
            foreach (BlockItemData data in converted.BlockValue.ContentData)
            {
                if (!blockConfigMap.ContainsKey(data.ContentTypeKey))
                {
                    continue;
                }

                IPublishedElement?element = _blockConverter.ConvertToElement(data, referenceCacheLevel, preview);
                if (element == null)
                {
                    continue;
                }

                contentPublishedElements[element.Key] = element;
            }

            // If there are no content elements, it doesn't matter what is stored in layout
            if (contentPublishedElements.Count == 0)
            {
                return(BlockListModel.Empty);
            }

            // Convert the settings data
            var settingsPublishedElements = new Dictionary <Guid, IPublishedElement>();
            var validSettingsElementTypes = blockConfigMap.Values.Select(x => x.SettingsElementTypeKey)
                                            .Where(x => x.HasValue).Distinct().ToList();
            foreach (BlockItemData data in converted.BlockValue.SettingsData)
            {
                if (!validSettingsElementTypes.Contains(data.ContentTypeKey))
                {
                    continue;
                }

                IPublishedElement?element = _blockConverter.ConvertToElement(data, referenceCacheLevel, preview);
                if (element is null)
                {
                    continue;
                }

                settingsPublishedElements[element.Key] = element;
            }

            // Cache constructors locally (it's tied to the current IPublishedSnapshot and IPublishedModelFactory)
            var blockListItemActivator = new BlockListItemActivator(_blockConverter);

            var list = new List <BlockListItem>();
            foreach (BlockListLayoutItem layoutItem in blockListLayout)
            {
                // Get the content reference
                var contentGuidUdi = (GuidUdi?)layoutItem.ContentUdi;
                if (contentGuidUdi is null ||
                    !contentPublishedElements.TryGetValue(contentGuidUdi.Guid, out IPublishedElement? contentData))
                {
                    continue;
                }

                if (!blockConfigMap.TryGetValue(
                        contentData.ContentType.Key,
                        out BlockListConfiguration.BlockConfiguration? blockConfig))
                {
                    continue;
                }

                // Get the setting reference
                IPublishedElement?settingsData = null;
                var settingGuidUdi             = (GuidUdi?)layoutItem.SettingsUdi;
                if (settingGuidUdi is not null)
                {
                    settingsPublishedElements.TryGetValue(settingGuidUdi.Guid, out settingsData);
                }

                // This can happen if they have a settings type, save content, remove the settings type, and display the front-end page before saving the content again
                // We also ensure that the content types match, since maybe the settings type has been changed after this has been persisted
                if (settingsData is not null && (!blockConfig.SettingsElementTypeKey.HasValue ||
                                                 settingsData.ContentType.Key != blockConfig.SettingsElementTypeKey))
                {
                    settingsData = null;
                }

                // Create instance (use content/settings type from configuration)
                BlockListItem layoutRef = blockListItemActivator.CreateInstance(blockConfig.ContentElementTypeKey, blockConfig.SettingsElementTypeKey, contentGuidUdi, contentData, settingGuidUdi, settingsData);

                list.Add(layoutRef);
            }

            return(new BlockListModel(list));
        }
    }