private ArticleField DeserializeBackwardField(BackwardRelationField fieldInDef, IProductDataSource productDataSource, DBConnector connector, Context context) { if (string.IsNullOrEmpty(fieldInDef.FieldName)) { throw new Exception("BackwardArticleField definition should have non-empty FieldName"); } IEnumerable <IProductDataSource> containersCollection = productDataSource.GetContainersCollection(fieldInDef.FieldName); var backwardArticleField = new BackwardArticleField { SubContentId = fieldInDef.Content.ContentId, }; if (containersCollection != null) { foreach (Article article in containersCollection.Select(x => DeserializeArticle(x, fieldInDef.Content, connector, context))) { backwardArticleField.Items.Add(article.Id, article); } } return(backwardArticleField); }
private ArticleField CloneField(ArticleField field, string fieldName, Dictionary <Article, Article> articleMap) { var pField = field as PlainArticleField; var sField = field as SingleArticleField; var mField = field as MultiArticleField; var eField = field as ExtensionArticleField; var bField = field as BackwardArticleField; var vField = field as VirtualArticleField; var vmField = field as VirtualMultiArticleField; ArticleField clonnedField; if (pField != null) { clonnedField = new PlainArticleField { NativeValue = pField.NativeValue, Value = pField.Value, PlainFieldType = pField.PlainFieldType }; } else if (eField != null) { clonnedField = new ExtensionArticleField { Aggregated = eField.Aggregated, SubContentId = eField.SubContentId, Item = eField.Item == null ? null : articleMap[eField.Item], Value = eField.Value }; } else if (sField != null) { clonnedField = new SingleArticleField { Aggregated = sField.Aggregated, SubContentId = sField.SubContentId, Item = sField.Item == null ? null : articleMap[sField.Item] }; } else if (bField != null) { clonnedField = new BackwardArticleField { SubContentId = bField.SubContentId, Items = bField.Items.ToDictionary(itm => itm.Key, itm => articleMap[itm.Value]), RelationGroupName = bField.RelationGroupName }; } else if (mField != null) { clonnedField = new MultiArticleField { SubContentId = mField.SubContentId, Items = mField.Items.ToDictionary(itm => itm.Key, itm => articleMap[itm.Value]) }; } else if (vField != null) { clonnedField = new VirtualArticleField { Fields = vField.Fields }; } else if (vmField != null) { clonnedField = new VirtualMultiArticleField { VirtualArticles = vmField.VirtualArticles .Select(f => CloneField(f, fieldName, articleMap) as VirtualArticleField) .ToArray() }; } else { throw new Exception($"Cant't process field {field.FieldName} for localization"); } clonnedField.FieldName = fieldName; clonnedField.ContentId = field.ContentId; clonnedField.FieldId = field.FieldId; clonnedField.CustomProperties = field.CustomProperties; clonnedField.FieldDisplayName = field.FieldDisplayName; return(clonnedField); }
private Article GetProduct(JToken productToken, JToken contentToken) { int contentId = contentToken.Value <int>("ContentId"); int statusTypeId = productToken.Value <int>("STATUS_TYPE_ID"); string statusName = _statusProvider.GetStatusName(statusTypeId); bool isPublished = statusName == PublishedStatusd; var product = new Article { Id = productToken.Value <int>("Id"), Archived = productToken.Value <bool>("ARCHIVE"), Visible = productToken.Value <bool>("VISIBLE"), IsPublished = isPublished, Status = statusName, Created = productToken.Value <DateTime>("CREATED"), Modified = productToken.Value <DateTime>("MODIFIED"), ContentId = contentId, ContentName = contentToken.Value <string>("ContentName"), ContentDisplayName = contentToken.Value <string>("ContentDisplayName"), }; foreach (var fieldToken in contentToken["PlainField"]) { var plainField = new PlainArticleField { ContentId = product.ContentId, PlainFieldType = GetFieldType(fieldToken) }; var numberType = GetNumberType(fieldToken); UpdateField(plainField, fieldToken); SetValue(plainField, productToken, numberType); product.Fields[plainField.FieldName] = plainField; } foreach (var fieldToken in contentToken["EntityField"]) { var fieldType = GetFieldType(fieldToken); if (fieldType == PlainFieldType.M2MRelation || fieldType == PlainFieldType.M2ORelation) { var multiField = new MultiArticleField { ContentId = product.ContentId }; UpdateField(multiField, fieldToken); var articleTokens = productToken[multiField.FieldName]; if (articleTokens != null) { foreach (var articleToken in articleTokens) { var childContentToken = fieldToken["Content"]; var article = GetProduct(articleToken, childContentToken); multiField.Items.Add(article.Id, article); } } product.Fields[multiField.FieldName] = multiField; } else if (fieldType == PlainFieldType.O2MRelation) { var singleField = new SingleArticleField { ContentId = product.ContentId }; UpdateField(singleField, fieldToken); var articleToken = productToken[singleField.FieldName]; if (articleToken != null) { var childContentToken = fieldToken["Content"]; var article = GetProduct(articleToken, childContentToken); singleField.Item = article; } product.Fields[singleField.FieldName] = singleField; } else { throw new Exception($"EntityField has unsupportable type {fieldType}"); } } foreach (var fieldToken in contentToken["ExtensionField"]) { var extensionField = new ExtensionArticleField { ContentId = product.ContentId }; UpdateField(extensionField, fieldToken); var extensionId = productToken.Value <int>(extensionField.FieldName); var childContentToken = fieldToken["Contents"].FirstOrDefault(c => c.Value <int>("ContentId") == extensionId); if (childContentToken != null) { var article = GetProduct(productToken, childContentToken); article.Id = 0; extensionField.Value = childContentToken.Value <string>("ContentId"); extensionField.Item = article; product.Fields[extensionField.FieldName] = extensionField; } } foreach (var fieldToken in contentToken["BackwardRelationField"]) { var backwardField = new BackwardArticleField { ContentId = product.ContentId, }; UpdateField(backwardField, fieldToken); var articleToken = productToken[backwardField.FieldName]; if (articleToken != null) { foreach (var t in articleToken) { var childContentToken = fieldToken["Content"]; var article = GetProduct(t, childContentToken); backwardField.Items.Add(article.Id, article); } } product.Fields[backwardField.FieldName] = backwardField; } return(product); }
/// <exception cref="ArgumentNullException" /> /// <exception cref="InvalidOperationException" /> private void ProcessArticlesTree(Article newArticle, Article existingArticle, Content definition) { if (newArticle == null || !_filter.Matches(newArticle)) { return; } if (!_filter.Matches(existingArticle)) { existingArticle = null; } if (definition == null) { throw new ArgumentNullException(nameof(definition)); } ValidateDates(newArticle, existingArticle); ArticleData newArticleUpdateData = new ArticleData { ContentId = definition.ContentId, Id = newArticle.Id }; List <int> plainFieldIds = definition.Fields .Where(x => x is PlainField) .Select(x => x.FieldId) .ToList(); if (definition.LoadAllPlainFields) { plainFieldIds.AddRange( _fieldService.List(definition.ContentId) .Where(x => x.RelationType == RelationType.None && definition.Fields.All(y => y.FieldId != x.Id)) .Select(x => x.Id)); } // TODO: исключаем Readonly поля var updatedFields = newArticle.Fields.Values .OfType <PlainArticleField>() .Where(x => plainFieldIds.Contains(x.FieldId.Value) && (existingArticle == null || existingArticle.Fields.Values .OfType <PlainArticleField>() .All(y => y.FieldId != x.FieldId || !HasEqualNativeValues(x, y)))) .Select(x => new FieldData { Id = x.FieldId.Value, Value = x.Value }); newArticleUpdateData.Fields.AddRange(updatedFields); var associationFieldsInfo = ( from fieldDef in definition.Fields.OfType <Association>() join field in newArticle.Fields.Values on fieldDef.FieldId equals field.FieldId select new { field, oldField = existingArticle?.Fields.Values.SingleOrDefault(x => x.FieldId == field.FieldId), fieldDef }).ToArray(); foreach (var fieldToSyncInfo in associationFieldsInfo) { if (fieldToSyncInfo.fieldDef is BackwardRelationField backwardRelationFieldDef) { BackwardArticleField oldField = (BackwardArticleField)fieldToSyncInfo.oldField; BackwardArticleField field = (BackwardArticleField)fieldToSyncInfo.field; int[] idsToAdd = field.GetArticles(_filter) .Where(x => oldField == null || oldField.GetArticles(_filter).All(y => y.Id != x.Id)) .Select(x => x.Id) .ToArray(); int[] idsToRemove = oldField?.GetArticles(_filter) .Select(x => x.Id) .Where(x => field.GetArticles(_filter).All(y => y.Id != x)) .ToArray() ?? new int[0]; if (idsToAdd.Any()) { _updateData.AddRange(idsToAdd.Select(x => new ArticleData { Id = x, ContentId = backwardRelationFieldDef.Content.ContentId, Fields = new List <FieldData> { new FieldData { Id = field.FieldId.Value, ArticleIds = new[] { newArticle.Id } } } })); } if (idsToRemove.Any()) { if (backwardRelationFieldDef.DeletingMode == DeletingMode.Delete) { foreach (int idToRemove in idsToRemove) { _articlesToDelete[idToRemove] = backwardRelationFieldDef.Content; } } else { _updateData.AddRange(idsToRemove.Select(x => new ArticleData { Id = x, ContentId = backwardRelationFieldDef.Content.ContentId })); } } } else if (fieldToSyncInfo.fieldDef is ExtensionField extensionFieldDef) { ExtensionArticleField oldField = (ExtensionArticleField)fieldToSyncInfo.oldField; ExtensionArticleField field = (ExtensionArticleField)fieldToSyncInfo.field; if (oldField == null || field.Value != oldField.Value) { newArticleUpdateData.Fields.Add(new FieldData { Id = extensionFieldDef.FieldId, Value = field.Value, ArticleIds = field.Item == null ? null : new[] { field.Item.Id } }); if (oldField?.Item != null) { _articlesToDelete[oldField.Item.Id] = extensionFieldDef .ContentMapping[oldField.Item.ContentId]; } } } else if (fieldToSyncInfo.field is SingleArticleField) { SingleArticleField oldField = (SingleArticleField)fieldToSyncInfo.oldField; SingleArticleField field = (SingleArticleField)fieldToSyncInfo.field; EntityField entityFieldDef = (EntityField)fieldToSyncInfo.fieldDef; Article item = field.GetItem(_filter); Article oldItem = oldField?.GetItem(_filter); if (item?.Id != oldItem?.Id) { newArticleUpdateData.Fields.Add(new FieldData { Id = field.FieldId.Value, ArticleIds = item == null ? null : new[] { item.Id } }); if (oldItem != null && entityFieldDef.DeletingMode == DeletingMode.Delete) { _articlesToDelete[oldItem.Id] = entityFieldDef.Content; } } } else if (fieldToSyncInfo.field is MultiArticleField) { MultiArticleField oldField = (MultiArticleField)fieldToSyncInfo.oldField; MultiArticleField field = (MultiArticleField)fieldToSyncInfo.field; EntityField entityFieldDef = (EntityField)fieldToSyncInfo.fieldDef; var items = field.GetArticles(_filter).ToArray(); var oldItems = oldField?.GetArticles(_filter).ToArray(); if (items.Length != (oldItems?.Length ?? 0) || items.Any(x => oldItems.All(y => y.Id != x.Id))) { newArticleUpdateData.Fields.Add(new FieldData { Id = field.FieldId.Value, ArticleIds = items.Select(x => x.Id).ToArray() }); if (entityFieldDef.DeletingMode == DeletingMode.Delete) { int[] idsToRemove = oldItems? .Where(x => items.All(y => y.Id != x.Id)) .Select(x => x.Id) .ToArray() ?? new int[0]; foreach (int idToRemove in idsToRemove) { _articlesToDelete[idToRemove] = entityFieldDef.Content; } } } } } if (newArticleUpdateData.Fields.Any()) { _updateData.Add(newArticleUpdateData); } foreach (var fieldInfo in associationFieldsInfo .Where(x => x.fieldDef.UpdatingMode == UpdatingMode.Update || x.fieldDef is ExtensionField)) { Article[] oldFieldsArticles = fieldInfo.oldField == null ? new Article[0] : GetChildArticles(fieldInfo.oldField, _filter).ToArray(); foreach (Article childArticle in GetChildArticles(fieldInfo.field, _filter)) { Content childArticleDef = fieldInfo.fieldDef.GetContents() .SingleOrDefault(x => x.ContentId == childArticle.ContentId); if (childArticleDef == null) { throw new InvalidOperationException($@"There is an conflict in product definition field {fieldInfo.field.FieldId} between ContentId={childArticle.ContentId} and Articleid={childArticle.Id}"); } Article oldChildArticle = oldFieldsArticles.SingleOrDefault(x => x.Id == childArticle.Id); ProcessArticlesTree(childArticle, oldChildArticle, childArticleDef); } } }