コード例 #1
0
        private ContentSchemaJsonRef GetSchemaRef(ContentSchema contentSchema, SchemaContext context)
        {
            string name = context.DefinitionNamesBySchema[contentSchema];

            return(new ContentSchemaJsonRef
            {
                ContentId = contentSchema.ContentId,
                Ref = $"#/{nameof(ProductSchema.Definitions)}/{name}"
            });
        }
コード例 #2
0
        /// <summary>
        /// Заполняем словарь пустыми схемами
        /// </summary>
        private void CreateEmptyContentSchemas(
            ContentSchema contentSchema, Dictionary <int, ContentSchema> shapesByContentId)
        {
            if (!shapesByContentId.ContainsKey(contentSchema.ContentId))
            {
                var copy = contentSchema.ShallowCopy();
                copy.Fields = new Dictionary <string, FieldSchema>();
                shapesByContentId[contentSchema.ContentId] = copy;
            }

            VisitChildSchemas(contentSchema, shapesByContentId, CreateEmptyContentSchemas);
        }
コード例 #3
0
        /// <summary>
        /// Построить схему корневого DPC-контента и набор ссылок на повторяющиеся контенты
        /// </summary>
        private ProductSchema GetProductSchema(ContentSchema contentSchema, SchemaContext context)
        {
            context.DefinitionNamesBySchema = context.RepeatedSchemas
                                              .GroupBy(schema => String.IsNullOrEmpty(schema.ContentName)
                    ? $"Content{schema.ContentId}"
                    : schema.ContentName)
                                              .SelectMany(group => group.Select((schema, i) => new
            {
                Key   = schema,
                Value = $"{group.Key}{(i == 0 ? "" : i.ToString())}",
            }))
                                              .ToDictionary(pair => pair.Key, pair => pair.Value);

            return(new ProductSchema
            {
                Content = DeduplicateContentSchema(contentSchema, context, new HashSet <ContentSchema>()),

                Definitions = context.DefinitionNamesBySchema
                              .ToDictionary(pair => pair.Value, pair => pair.Key),
            });
        }
コード例 #4
0
 private void VisitChildSchemas(
     ContentSchema contentSchema,
     Dictionary <int, ContentSchema> schemasByContentId,
     Action <ContentSchema, Dictionary <int, ContentSchema> > action)
 {
     foreach (FieldSchema fieldSchema in contentSchema.Fields.Values)
     {
         if (fieldSchema is RelationFieldSchema relationFieldSchema)
         {
             if (relationFieldSchema.RelatedContent is ContentSchema childContentSchema)
             {
                 action.Invoke(childContentSchema, schemasByContentId);
             }
         }
         else if (fieldSchema is ExtensionFieldSchema extensionFieldSchema)
         {
             foreach (var childContentSchema in extensionFieldSchema.ExtensionContents.Values.OfType <ContentSchema>())
             {
                 action.Invoke(childContentSchema, schemasByContentId);
             }
         }
     }
 }
コード例 #5
0
        /// <summary>
        /// Генерация схемы для редактирования контентов
        /// </summary>
        /// <exception cref="NotSupportedException" />
        /// <exception cref="InvalidOperationException" />
        public ProductSchema GetProductSchema(Content content)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            _contentService.LoadStructureCache();
            _fieldService.LoadStructureCache();

            VirtualFieldContext virtualFieldContext = _virtualFieldContextService.GetVirtualFieldContext(content);

            var context = new SchemaContext
            {
                Dictionaries  = content.Fields.OfType <Dictionaries>().SingleOrDefault(),
                IgnoredFields = virtualFieldContext.IgnoredFields,
            };

            ContentSchema contentSchema = GetContentSchema(content, context, "");

            ProductSchema productSchema = GetProductSchema(contentSchema, context);

            return(productSchema);
        }
コード例 #6
0
        /// <summary>
        /// Объединяем поля схем контентов
        /// </summary>
        private void FillMergedContentSchemas(
            ContentSchema contentSchema, Dictionary <int, ContentSchema> schemasByContentId)
        {
            ContentSchema mergedContentSchema = schemasByContentId[contentSchema.ContentId];

            if (!contentSchema.IsReadOnly)
            {
                // Один и тот же контент может использоваться для чтения и для изменения
                // в разных частях схемы. В этом случае считаем, что контент не является ReadOnly.
                mergedContentSchema.IsReadOnly = false;
            }
            if (!contentSchema.ForExtension)
            {
                // Один и тот же контент может использоваться как Extension и как Relation
                // в разных частях схемы. В этом случае считаем, что контент не является Extension.
                mergedContentSchema.ForExtension = false;
            }

            foreach (FieldSchema fieldSchema in contentSchema.Fields.Values)
            {
                // Перезаписываем все сложные поля, потому что для одного и того же контента,
                // в одном месте ProductDefinition заданное поле может быть RelationField | ExtensionField,
                // а в другом месте у контента стоит флаг LoadAllPlainFields,
                // и поле является PlainField c типом FieldExactTyes.O2MRelation | FieldExactTyes.Classifier
                if (fieldSchema is ExtensionFieldSchema extFieldSchema)
                {
                    var copy = extFieldSchema.ShallowCopy();

                    copy.ExtensionContents = extFieldSchema.ExtensionContents.ToDictionary(
                        pair => pair.Key,
                        pair => (IContentSchema) new ContentSchemaIdRef
                    {
                        ContentId = pair.Value.ContentId,
                    });

                    // Объединяем наборы допустимых контентов
                    if (mergedContentSchema.Fields
                        .TryGetValue(fieldSchema.FieldName, out FieldSchema mergedFieldSchema) &&
                        mergedFieldSchema is ExtensionFieldSchema mergedExtensionSchema)
                    {
                        foreach (var pair in mergedExtensionSchema.ExtensionContents)
                        {
                            if (!copy.ExtensionContents.ContainsKey(pair.Key))
                            {
                                copy.ExtensionContents[pair.Key] = pair.Value;
                            }
                        }
                    }

                    mergedContentSchema.Fields[fieldSchema.FieldName] = copy;
                }
                else if (fieldSchema is SingleRelationFieldSchema singleFieldSchema)
                {
                    var copy = singleFieldSchema.ShallowCopy();
                    copy.RelatedContent = new ContentSchemaIdRef
                    {
                        ContentId = singleFieldSchema.RelatedContent.ContentId,
                    };
                    copy.ClearContextDependentProps();
                    mergedContentSchema.Fields[fieldSchema.FieldName] = copy;
                }
                else if (fieldSchema is MultiRelationFieldSchema multiFieldSchema)
                {
                    var copy = multiFieldSchema.ShallowCopy();
                    copy.RelatedContent = new ContentSchemaIdRef
                    {
                        ContentId = multiFieldSchema.RelatedContent.ContentId,
                    };
                    copy.ClearContextDependentProps();
                    mergedContentSchema.Fields[fieldSchema.FieldName] = copy;
                }
                else if (!mergedContentSchema.Fields.ContainsKey(fieldSchema.FieldName))
                {
                    mergedContentSchema.Fields[fieldSchema.FieldName] = fieldSchema;
                }

                VisitChildSchemas(contentSchema, schemasByContentId, FillMergedContentSchemas);
            }
        }
コード例 #7
0
        /// <exception cref="NotSupportedException" />
        /// <exception cref="InvalidOperationException" />
        private RelationFieldSchema GetRelationFieldSchema(
            EntityField entityField, Quantumart.QP8.BLL.Field qpField, SchemaContext context, string path)
        {
            ContentSchema contentSchema = GetContentSchema(entityField.Content, context, path);

            string relationCondition = _editorPreloadingService.GetRelationCondition(entityField, qpField);

            ArticleObject[] preloadedArticles = new ArticleObject[0];
            if (entityField.PreloadingMode == PreloadingMode.Eager)
            {
                preloadedArticles = _editorPreloadingService.PreloadRelationArticles(
                    entityField,
                    relationCondition,
                    context.VisitedPreloadedArticles,
                    context.Dictionaries);
            }

            string[] displayFieldNames = contentSchema.Fields.Values
                                         .OfType <PlainFieldSchema>()
                                         .Where(f => f.FieldType != FieldExactTypes.Textbox && f.FieldType != FieldExactTypes.VisualEdit)
                                         .OrderByDescending(f => f.ViewInList)
                                         .ThenBy(f => f.FieldOrder)
                                         .Take(Math.Max(qpField.ListFieldTitleCount, 1))
                                         .Select(f => f.FieldName)
                                         .ToArray();

            if (qpField.ExactType == FieldExactTypes.O2MRelation && !(entityField is BackwardRelationField) ||
                qpField.ExactType == FieldExactTypes.M2ORelation && entityField is BackwardRelationField)
            {
                return(new SingleRelationFieldSchema
                {
                    RelatedContent = contentSchema,
                    UpdatingMode = entityField.UpdatingMode,
                    IsDpcBackwardField = entityField is BackwardRelationField,
                    RelationCondition = relationCondition,
                    DisplayFieldNames = displayFieldNames,
                    PreloadingMode = entityField.PreloadingMode,
                    PreloadedArticles = preloadedArticles,
                });
            }
            if (qpField.ExactType == FieldExactTypes.M2MRelation ||
                qpField.ExactType == FieldExactTypes.O2MRelation && entityField is BackwardRelationField ||
                qpField.ExactType == FieldExactTypes.M2ORelation && !(entityField is BackwardRelationField))
            {
                int? orderFieldId = qpField.TreeOrderFieldId ?? qpField.ListOrderFieldId ?? qpField.OrderFieldId;
                bool orderByTitle = qpField.TreeOrderByTitle || qpField.ListOrderByTitle || qpField.OrderByTitle;

                string orderByFieldName = contentSchema.Fields.Values
                                          .OfType <PlainFieldSchema>()
                                          .Where(f => f.FieldId == orderFieldId)
                                          .Select(f => f.FieldName)
                                          .FirstOrDefault();

                if (orderByFieldName == null && orderByTitle)
                {
                    orderByFieldName = displayFieldNames.FirstOrDefault();
                }

                int?maxDataListItemCount = null;

                if (qpField.ExactType == FieldExactTypes.M2ORelation && qpField.BackRelationId != null)
                {
                    // MaxDataListItemCount лежит в соотв. поле O2MRelation
                    var reverseField = _fieldService.Read(qpField.BackRelationId.Value);
                    if (reverseField.MaxDataListItemCount > 0)
                    {
                        maxDataListItemCount = reverseField.MaxDataListItemCount;
                    }
                }
                else if (qpField.MaxDataListItemCount > 0)
                {
                    maxDataListItemCount = qpField.MaxDataListItemCount;
                }

                return(new MultiRelationFieldSchema
                {
                    RelatedContent = contentSchema,
                    UpdatingMode = entityField.UpdatingMode,
                    IsDpcBackwardField = entityField is BackwardRelationField,
                    RelationCondition = relationCondition,
                    DisplayFieldNames = displayFieldNames,
                    OrderByFieldName = orderByFieldName,
                    MaxDataListItemCount = maxDataListItemCount,
                    PreloadingMode = entityField.PreloadingMode,
                    PreloadedArticles = preloadedArticles,
                });
            }
            throw new NotSupportedException($"Relation type {qpField.ExactType} is not supported");
        }
コード例 #8
0
        /// <summary>
        /// Рекурсивно обходит <see cref="Content"/>, генерирует корневую схему и заполняет
        /// <see cref="SchemaContext.SchemasByContent"/> - созданные схемы контентов
        /// и <see cref="SchemaContext.RepeatedContents"/> - повторяющиеся контенты
        /// </summary>
        /// <exception cref="NotSupportedException" />
        /// <exception cref="InvalidOperationException" />
        private ContentSchema GetContentSchema(Content content, SchemaContext context, string path)
        {
            if (context.SchemasByContent.ContainsKey(content))
            {
                ContentSchema repeatedSchema = context.SchemasByContent[content];
                context.RepeatedSchemas.Add(repeatedSchema);
                return(repeatedSchema);
            }

            ContentSchema contentSchema = CreateContentSchema(content, path);

            context.SchemasByContent[content] = contentSchema;

            var qpFields = _fieldService.List(content.ContentId).ToArray();

            var fieldsToAdd = content.Fields
                              .Where(field => !(field is Dictionaries || field is BaseVirtualField) &&
                                     !context.IgnoredFields.Contains(Tuple.Create(content, field)));

            foreach (Field field in fieldsToAdd)
            {
                if (field.FieldName == null)
                {
                    throw new InvalidOperationException(
                              $"FieldName is null: {new { field.FieldId, field.FieldName }}");
                }

                var qpField = field is BackwardRelationField
                        ? _fieldService.Read(field.FieldId)
                        : qpFields.SingleOrDefault(f => f.Id == field.FieldId);

                if (qpField == null)
                {
                    throw new InvalidOperationException(
                        $@"There is a field id={field.FieldId} specified in the definition and missing in the content id={content.ContentId}"
                              );
                }
                if (qpField.ExactType != FieldExactTypes.DynamicImage)
                {
                    contentSchema.Fields[field.FieldName] = GetFieldSchema(field, qpField, context, path);
                }
            }

            if (content.LoadAllPlainFields)
            {
                var qpFieldsToAdd = qpFields
                                    .Where(qpField => qpField.RelationType == Quantumart.QP8.BLL.RelationType.None &&
                                           qpField.ExactType != FieldExactTypes.DynamicImage &&
                                           content.Fields.All(field => field.FieldId != qpField.Id) &&
                                           !context.IgnoredFields
                                           .Any(tuple => tuple.Item1.Equals(content) &&
                                                tuple.Item2.FieldId == qpField.Id));

                foreach (var qpField in qpFieldsToAdd)
                {
                    contentSchema.Fields[qpField.Name] = GetFieldSchema(null, qpField, context, path);
                }
            }

            contentSchema.DisplayFieldName = contentSchema.Fields.Values
                                             .OfType <PlainFieldSchema>()
                                             .Where(f => f.FieldType == FieldExactTypes.String)
                                             .OrderByDescending(f => f.ViewInList)
                                             .ThenBy(f => f.FieldOrder)
                                             .Select(f => f.FieldName)
                                             .FirstOrDefault();

            return(contentSchema);
        }