private void FillVirtualFieldsInfo(
            Content content, VirtualFieldContext context, HashSet <Content> visitedContents)
        {
            if (visitedContents.Contains(content))
            {
                return;
            }
            visitedContents.Add(content);

            foreach (Field field in content.Fields)
            {
                if (field is BaseVirtualField baseField)
                {
                    ProcessVirtualField(baseField, content, context);
                }
                else if (field is EntityField entityField)
                {
                    FillVirtualFieldsInfo(entityField.Content, context, visitedContents);
                }
                else if (field is ExtensionField extensionField)
                {
                    foreach (Content extContent in extensionField.ContentMapping.Values)
                    {
                        FillVirtualFieldsInfo(extContent, context, visitedContents);
                    }
                }
            }
        }
        /// <summary>
        /// Рекурсивно обходит <see cref="Content"/> и заполняет
        /// <see cref="VirtualFieldContext.IgnoredFields"/> - список полей которые надо игнорировать при создании схемы
        /// и <see cref="VirtualFieldContext.VirtualFields"/> - значения вирутальных полей
        /// </summary>
        /// <exception cref="InvalidOperationException" />
        public VirtualFieldContext GetVirtualFieldContext(Content content)
        {
            var context = new VirtualFieldContext();

            FillVirtualFieldsInfo(content, context, new HashSet <Content>());

            return(context);
        }
예제 #3
0
        /// <exception cref="NotSupportedException" />
        /// <exception cref="InvalidOperationException" />
        private JSchema GetSchema(Content definition, bool forList, bool includeRegionTags, bool excludeVirtualFields)
        {
            _contentService.LoadStructureCache();
            _fieldService.LoadStructureCache();

            VirtualFieldContext virtualFieldContext = _virtualFieldContextService.GetVirtualFieldContext(definition);

            var context = new SchemaContext
            {
                VirtualFields = virtualFieldContext.VirtualFields,
                IgnoredFields = virtualFieldContext.IgnoredFields,
                ExcludeVirtualFields = excludeVirtualFields
            };

            JSchema rootSchema = GetSchemaRecursive(definition, context, forList);
            
            if (includeRegionTags)
            {
                JSchema schemaWithRegionTags = new JSchema { Type = JSchemaType.Object };

                schemaWithRegionTags.Properties.Add(ProductProp, rootSchema);

                JSchema regionTagsSchema = new JSchema { Type = JSchemaType.Array };

                JSchema regionTagSchema = new JSchema { Type = JSchemaType.Object };

                regionTagSchema.Properties.Add("title", new JSchema { Type = JSchemaType.String });

                JSchema valuesSchema = new JSchema { Type = JSchemaType.Array };

                JSchema valueSchema = new JSchema { Type = JSchemaType.Object };

                valueSchema.Properties.Add("value", new JSchema { Type = JSchemaType.String });

                JSchema regionIdsSchema = new JSchema { Type = JSchemaType.Array };

                regionIdsSchema.Items.Add(new JSchema { Type = JSchemaType.Integer });

                valueSchema.Properties.Add("regionsId", regionIdsSchema);

                valueSchema.Required.Add("regionsId");

                valueSchema.Required.Add("value");

                valuesSchema.Items.Add(valueSchema);

                regionTagSchema.Properties.Add("values", valuesSchema);

                regionTagSchema.Required.Add("title");

                regionTagSchema.Required.Add("values");

                regionTagsSchema.Items.Add(regionTagSchema);

                schemaWithRegionTags.Properties.Add(RegionTagsProp, regionTagsSchema);

                FillSchemaDefinitions(schemaWithRegionTags, context);

                DeduplicateJsonSchema(schemaWithRegionTags, context);

                return schemaWithRegionTags;
            }
            
            FillSchemaDefinitions(rootSchema, context);

            DeduplicateJsonSchema(rootSchema, context);

            return rootSchema;
        }
        private void ProcessVirtualField(
            BaseVirtualField baseVirtualField, Content definition, VirtualFieldContext context)
        {
            if (baseVirtualField is VirtualMultiEntityField virtualMultiEntityField)
            {
                string path = virtualMultiEntityField.Path;

                var virtualFieldKey = Tuple.Create(definition, path);

                if (context.VirtualFields.ContainsKey(virtualFieldKey))
                {
                    return;
                }

                Field foundField = _virtualFieldPathEvaluator
                                   .GetFieldByPath(path, definition, out bool hasFilter, out Content parent);

                if (!hasFilter)
                {
                    context.IgnoredFields.Add(Tuple.Create(parent, foundField));
                }

                context.VirtualFields[virtualFieldKey] = foundField;

                if (foundField is EntityField foundEntityField)
                {
                    foreach (BaseVirtualField childField in virtualMultiEntityField.Fields)
                    {
                        ProcessVirtualField(childField, foundEntityField.Content, context);
                    }
                }
                else
                {
                    throw new InvalidOperationException(
                              "В Path VirtualMultiEntityField должны быть только поля EntityField или наследники");
                }
            }
            else if (baseVirtualField is VirtualEntityField virtualEntityField)
            {
                foreach (BaseVirtualField childField in virtualEntityField.Fields)
                {
                    ProcessVirtualField(childField, definition, context);
                }
            }
            else if (baseVirtualField is VirtualField virtualField)
            {
                string path = virtualField.Path;

                var virtualFieldKey = Tuple.Create(definition, path);

                if (context.VirtualFields.ContainsKey(virtualFieldKey))
                {
                    return;
                }

                Field fieldToMove = _virtualFieldPathEvaluator
                                    .GetFieldByPath(path, definition, out bool hasFilter, out Content parent);

                if (!hasFilter)
                {
                    context.IgnoredFields.Add(Tuple.Create(parent, fieldToMove));
                }

                context.VirtualFields[virtualFieldKey] = fieldToMove;
            }
        }