protected virtual bool HasConsequentialChanges(ItemChanges changes) { // properties, e.g. template, etc are always consequential if (changes.HasPropertiesChanged) { return(true); } foreach (FieldChange change in changes.FieldChanges) { if (change.OriginalValue == change.Value) { continue; } if (change.FieldID == FieldIDs.Revision) { continue; } if (change.FieldID == FieldIDs.Updated) { continue; } if (!_fieldPredicate.Includes(change.FieldID).IsIncluded) { continue; } return(true); } _logger.SaveRejectedAsInconsequential(_serializationProvider.LogName, changes); return(false); }
protected internal virtual void UpdateLink(Item item, ItemChanges changes) { PropertyChange propertyChange; if (!changes.Properties.TryGetValue("name", out propertyChange)) { return; } string name = propertyChange.OriginalValue as string; string str = propertyChange.Value as string; if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(str)) { return; } string elementType = GetElementType(item.TemplateID); if (elementType == null) { return; } XElement xelement = Find(elementType, item.ID, name); if (xelement != null) { xelement.SetAttributeValue("id", item.ID); xelement.SetAttributeValue((elementType == "campaign" ? "title" : "name"), str); } AcceptChanges(); }
public void SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (DisableSerialization) { return; } Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); var sourceItem = GetItemWithoutCache(changes.Item); if (!_predicate.Includes(sourceItem).IsIncluded) { return; } string oldName = changes.Renamed ? changes.Properties["name"].OriginalValue.ToString() : string.Empty; if (changes.Renamed && !oldName.Equals(sourceItem.Name, StringComparison.Ordinal)) // it's a rename, in which the name actually changed (template builder will cause 'renames' for the same name!!!) { _serializationProvider.RenameSerializedItem(sourceItem, oldName); _logger.RenamedItem(_serializationProvider.LogName, sourceItem, oldName); } else if (HasConsequentialChanges(changes)) // it's a simple update - but we reject it if only inconsequential fields (last updated, revision) were changed - again, template builder FTW { _serializationProvider.SerializeItem(sourceItem); _logger.SavedItem(_serializationProvider.LogName, sourceItem, "Saved"); } }
public bool SaveItem(ITreeNodeContent node, ItemChanges changes) { if (!changes.HasFieldsChanged) { return(false); } var productVariant = Product.Get(Convert.ToInt32(node.ItemId)); if (productVariant == null) { var message = string.Format("Product with id: {0} not found for ITreeNodeContent. ", node.ItemId); _loggingService.Debug <ProductCatalogTemplateBuilder>(message); throw new InvalidDataException(message); } foreach (FieldChange fieldChange in changes.FieldChanges) { UpdateVariantValue(fieldChange, productVariant, changes.Item); } ObjectFactory.Instance.Resolve <IPipeline <Product> >("SaveProduct").Execute(productVariant.ParentProduct); return(true); }
public bool SaveItem(ITreeNodeContent node, ItemChanges changes) { if (!changes.HasFieldsChanged) { return(false); } var category = Category.Get(int.Parse(node.ItemId)); if (category == null) { string message = string.Format("Category with id: {0} not found for ITreeNodeContent.", node.ItemId); _loggingService.Debug <ProductCatalogGroupTemplateBuilder>(message); throw new InvalidDataException(message); } foreach (FieldChange fieldChange in changes.FieldChanges) { UpdateStoreValueFor(fieldChange, category, changes.Item); } ObjectFactory.Instance.Resolve <IPipeline <Category> >("SaveCategory").Execute(category); return(true); }
public override bool SaveItem([NotNull] ItemDefinition itemDefinition, [NotNull] ItemChanges changes, [NotNull] CallContext context) { Assert.ArgumentNotNull(itemDefinition, nameof(itemDefinition)); Assert.ArgumentNotNull(changes, nameof(changes)); Assert.ArgumentNotNull(context, nameof(context)); #if DEBUG var timer = Stopwatch.StartNew(); #endif if (HeadProvider.GetItemDefinition(itemDefinition.ID, context) == null) { var item = changes.Item; Assert.IsNotNull(item, nameof(item)); if (!MigrateDefaultItem(itemDefinition, item, context)) { return(false); } } var saved = HeadProvider.SaveItem(itemDefinition, changes, context); #if DEBUG this.Trace(saved, timer, itemDefinition.ID, context); #endif return(saved); }
public void OnItemSaved(object sender, EventArgs args) { Item savedItem = null; ItemSavedRemoteEventArgs remoteArgs = args as ItemSavedRemoteEventArgs; ItemChanges savedItemChanges = null; //Thank you Mike Edwards! if (remoteArgs != null) { savedItem = remoteArgs.Item; savedItemChanges = remoteArgs.Changes; } else { savedItem = Event.ExtractParameter(args, 0) as Item; savedItemChanges = Event.ExtractParameter(args, 1) as ItemChanges; } if (savedItem != null && TemplateManager.IsFieldPartOfTemplate(SitecronConstants.SiteCronFieldIds.CronExpression, savedItem) && !StandardValuesManager.IsStandardValuesHolder(savedItem)) { if (savedItemChanges != null && !savedItemChanges.FieldChanges.ContainsAnyOf(SiteCronFieldIds.LastRunUTC, SiteCronFieldIds.NextRunUTC, SiteCronFieldIds.ExecutionTime, SiteCronFieldIds.LastRunLog) && !_inProcess.Contains(savedItem.ID)) { _inProcess.Add(savedItem.ID); Log.Info($"SiteCron based Item Saved/Created, reloading Jobs. {savedItem.Name} - {savedItem.ID.ToString()}", this); _scheduleManager.ScheduleAllJobs(); _inProcess.Remove(savedItem.ID); } else { Log.Info("SiteCron - Ignoring Saved Handler due to stats update.", this); } } else { try { string typeName = Settings.GetSetting(SitecronConstants.SettingsNames.SiteCronSavedHandlerType); if (!string.IsNullOrEmpty(typeName)) { Type type = Type.GetType(typeName); if (type != null) { object instance = Activator.CreateInstance(type); if (instance != null && instance is ISavedHandler) { MethodInfo method = type.GetMethod("OnItemSaved"); if (method != null) { method.Invoke(instance, new object[] { sender, args }); } } } } } catch (Exception ex) { Log.Error("SiteCron OnItemSaved Custom Type ERROR: " + ex.Message, ex, this); } } }
public string GetFieldChanges(ItemChanges itemChanges) { var fieldChanges = new FieldChanges(); if (itemChanges != null && itemChanges.FieldChanges != null) { foreach (FieldChange field in itemChanges.FieldChanges) { if (!IgnoredFields.Contains(field.FieldID)) { fieldChanges.Changes.Add(new Change() { FieldId = field.FieldID.Guid, FieldName = field.Definition.Name, OldValue = Settings.TraceOldvalue ? TruncateValue(field.FieldID, field.OriginalValue) : "[not-tracked]", NewValue = Settings.TraceNewValue ? TruncateValue(field.FieldID, field.Value) : "[not-tracked]" }); } } if (fieldChanges.Changes.Any()) { var s = JsonConvert.SerializeObject(fieldChanges); return(s); } } return(string.Empty); }
private bool EnsureSqlVersion(ItemDefinition itemDefinition, DataProvider sqlProvider, CallContext context) { var sqlVersion = GetSqlVersion(itemDefinition.ID, context, sqlProvider); if (sqlVersion != null) { return(true); } if (itemDefinition.ID == FolderId || ControllerType.GetAllNamespaces().ContainsKey(itemDefinition.ID.ToGuid()) || ControllerType.GetAllControllers().ContainsKey(itemDefinition.ID.ToGuid()) || ControllerAction.GetControllerAction(itemDefinition.ID) != null) { var parentId = GetParentID(itemDefinition, context) ?? sqlProvider.GetParentID(itemDefinition, context); var itemdef = GetItemDefinition(parentId, context) ?? sqlProvider.GetItemDefinition(parentId, context); if (!sqlProvider.CreateItem(itemDefinition.ID, itemDefinition.Name, itemDefinition.TemplateID, itemdef, context)) { return(false); } var item = Database.GetItem(itemDefinition.ID); var existingFields = new ItemChanges(item); foreach (Field field in item.Fields) { existingFields.SetFieldValue(field, item[field.ID]); } sqlProvider.SaveItem(itemDefinition, existingFields, context); return(true); } return(false); }
public bool SaveItem(ITreeNodeContent node, ItemChanges changes) { if (!changes.HasFieldsChanged) { return(false); } var catalog = ProductCatalog.Get(Convert.ToInt32(node.ItemId)); if (catalog == null) { var message = string.Format("Product Catalog with id: {0} not found for ITreeNodeContent. ", node.ItemId); _loggingService.Log <ProductCatalogTemplateBuilder>(message); throw new InvalidDataException(message); } foreach (FieldChange change in changes.FieldChanges) { UpdateCatalogValuesFor(change, catalog); } ObjectFactory.Instance.Resolve <IPipeline <ProductCatalog> >("SaveProductCatalog").Execute(catalog); return(true); }
public override void Process(object sender, EventArgs e) { try { Item item = Event.ExtractParameter <Item>(e, 0); ItemChanges changes = Event.ExtractParameter <ItemChanges>(e, 1); StringBuilder sb = new StringBuilder("<table><th>Field</th><th>Change</th>"); bool flag = false; foreach (FieldChange fieldChange in changes.FieldChanges) { Field field = item.Fields[fieldChange.FieldID]; if (field.Name.StartsWith("__") && fieldChange.OriginalValue != field.Value) { flag = true; sb.Append("<tr><td>"); sb.Append(Cleanse(field.Name)); sb.Append("</td><td>"); HtmlDiff.HtmlDiff diff = new HtmlDiff.HtmlDiff(fieldChange.OriginalValue, field.Value); sb.Append(diff.Build()); sb.Append("</td></tr>"); } } if (!flag) { return; } sb.Append("</table>"); LogEvent(item, sb.ToString()); } catch (Exception ex) { Log.Error("Problem auditing item save", ex, this); } }
public virtual void SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (DisableSerialization) { return; } Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); // get the item we're saving to evaluate with the predicate // NOTE: the item in this state may be incomplete as Sitecore can sometimes send partial item data and rely on changes to do the save // e.g. during package installations. So we have to merge the changes with any existing item data if we save it later, to keep it consistent. IItemData sourceItem = new ItemData(changes.Item); if (!_predicate.Includes(sourceItem).IsIncluded) { return; } string oldName = changes.Renamed ? changes.Properties["name"].OriginalValue.ToString() : string.Empty; if (changes.Renamed && !oldName.Equals(sourceItem.Name, StringComparison.Ordinal)) // it's a rename, in which the name actually changed (template builder will cause 'renames' for the same name!!!) { using (new DatabaseCacheDisabler()) { // disabling the DB caches while running this ensures that any children of the renamed item are retrieved with their proper post-rename paths and thus are not saved at their old location // this allows us to filter out any excluded children by predicate when the data store moves children var predicatedItem = new PredicateFilteredItemData(sourceItem, _predicate); _targetDataStore.MoveOrRenameItem(predicatedItem, changes.Item.Paths.ParentPath + "/" + oldName); } _logger.RenamedItem(_targetDataStore.FriendlyName, sourceItem, oldName); } else if (HasConsequentialChanges(changes)) // it's a simple update - but we reject it if only inconsequential fields (last updated, revision) were changed - again, template builder FTW { var existingSerializedItem = _targetDataStore.GetByPathAndId(sourceItem.Path, sourceItem.Id, sourceItem.DatabaseName); // generated an IItemData from the item changes we received, and apply those changes to the existing serialized item if any if (existingSerializedItem != null) { sourceItem = new ItemChangeApplyingItemData(existingSerializedItem, changes); } else { sourceItem = new ItemChangeApplyingItemData(changes); } _targetDataStore.Save(sourceItem); AddBlobsToCache(sourceItem); _logger.SavedItem(_targetDataStore.FriendlyName, sourceItem, "Saved"); } }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (!this.DataProviderDamHelper.EnabledMethods.Contains(DataProviderMethods.SaveItem)) { throw new NotSupportedException(); } return(base.SaveItem(itemDefinition, changes, context)); }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (!base.SaveItem(itemDefinition, changes, context)) return false; foreach (var provider in _unicornDataProviders) provider.SaveItem(itemDefinition, changes, context); return true; }
public void SaveItemReturnsFalse( [Greedy] FakeDataProvider sut, ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { // 'true' looks more correct here but numerous tests start failing then. sut.SaveItem(itemDefinition, changes, context).Should().BeFalse(); }
public bool SaveItem(ItemDefinition item, ItemChanges changes) { if (item.ID == _root.Id) { return(false); } return((from provider in _providers where provider.IsOneOfOurSitecoreItems(item.ID) select provider.SaveItem(item, changes)).FirstOrDefault()); }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { Item item = this.Database.GetItem(itemDefinition.ID); ItemDefinition parent = GetItemDefinition(item.ParentID, context); /* only creates the item if it does not exist yet */ CreateItem(itemDefinition.ID, itemDefinition.Name, itemDefinition.TemplateID, parent, context); bool result = base.SaveItem(itemDefinition, changes, context); return result; }
public void SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (DisableSerialization) { return; } Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); // get the item from the database (note: we don't allow TpSync to be a database here, because we handle that below) var sourceItem = GetSourceFromId(changes.Item.ID, allowTpSyncFallback: false); if (sourceItem == null) { if (DisableTransparentSync) { return; } // if TpSync is enabled, we wrap the item changes item directly; the TpSync item will NOT have the new changes as we need to write those here sourceItem = new ItemData(changes.Item); } if (!_predicate.Includes(sourceItem).IsIncluded) { return; } string oldName = changes.Renamed ? changes.Properties["name"].OriginalValue.ToString() : string.Empty; if (changes.Renamed && !oldName.Equals(sourceItem.Name, StringComparison.Ordinal)) // it's a rename, in which the name actually changed (template builder will cause 'renames' for the same name!!!) { using (new DatabaseCacheDisabler()) { // disabling the DB caches while running this ensures that any children of the renamed item are retrieved with their proper post-rename paths and thus are not saved at their old location // this allows us to filter out any excluded children by predicate when the data store moves children var predicatedItem = new PredicateFilteredItemData(sourceItem, _predicate); _targetDataStore.MoveOrRenameItem(predicatedItem, changes.Item.Paths.ParentPath + "/" + oldName); } _logger.RenamedItem(_targetDataStore.FriendlyName, sourceItem, oldName); } else if (HasConsequentialChanges(changes)) // it's a simple update - but we reject it if only inconsequential fields (last updated, revision) were changed - again, template builder FTW { _targetDataStore.Save(sourceItem); AddBlobsToCache(sourceItem); _logger.SavedItem(_targetDataStore.FriendlyName, sourceItem, "Saved"); } }
public void OnItemSaved(object sender, EventArgs args) { Item savedItem = null; ItemSavedRemoteEventArgs remoteArgs = args as ItemSavedRemoteEventArgs; ItemChanges savedItemChanges = Event.ExtractParameter(args, 1) as ItemChanges; //Thank you Mike Edwards! if (remoteArgs != null) { savedItem = remoteArgs.Item; } else { savedItem = Event.ExtractParameter(args, 0) as Item; } if (savedItem != null && SitecronConstants.Templates.SitecronJobTemplateID == savedItem.TemplateID) //matched Sitecron job template { if (savedItemChanges != null && savedItemChanges.FieldChanges.ContainsAnyOf(SiteCronFieldIds.LastRunUTC, SiteCronFieldIds.NextRunUTC, SiteCronFieldIds.ExecutionTime)) { Log.Info("Sitecron - Ignoring Saved Handler due to stats update.", this); } else { ScheduleHelper scheduler = new ScheduleHelper(); scheduler.InitializeScheduler(); } } else { try { string typeName = Settings.GetSetting(SitecronConstants.SettingsNames.SiteCronSavedHandlerType); if (!string.IsNullOrEmpty(typeName)) { Type type = Type.GetType(typeName); if (type != null) { object instance = Activator.CreateInstance(type); if (instance != null && instance is ISavedHandler) { MethodInfo method = type.GetMethod("OnItemSaved"); if (method != null) { method.Invoke(instance, new object[] { sender, args }); } } } } } catch (Exception ex) { Log.Error("Sitecron OnItemSaved Custom Type ERROR: " + ex.Message, ex, this); } } }
public void SaveItem(ID id, ItemChanges changes) { if (changes.HasFieldsChanged) { foreach (FieldChange fieldChange in changes.FieldChanges) { SaveField(id, fieldChange); } } }
public bool SaveItem(ItemDefinition item, ItemChanges changes) { MakeSureWeAreReady(); if (ItemIsContainedInDictionary(item.ID)) { return(_sitecoreItems[item.ID].SaveItem(changes)); } return(false); }
private void UpdateStoreName(ProductCatalogGroup store, string value, ItemChanges changes) { if (ProductCatalogGroup.SingleOrDefault(x => x.Name == value) != null) { _loggingService.Log <ProductCatalogGroupTemplateBuilder>(string.Format("Failed to update store name for store. Store with name: {0} already exists.", value)); return; } store.Name = value; }
private void UpdateItemFields([NotNull] ID itemId, [NotNull] ItemChanges changes) { Assert.ArgumentNotNull(itemId, "value"); lock ((object)this) { var now = DateTime.Now; var fullUpdate = changes.Item.RuntimeSettings.SaveAll; if (fullUpdate) { RemoveFields(itemId, changes.Item.Language, changes.Item.Version); } var updateOrder = new[] { DefaultFieldSharing.SharingType.Shared, DefaultFieldSharing.SharingType.Unversioned, DefaultFieldSharing.SharingType.Versioned }; foreach (var sharingType in updateOrder) { foreach (FieldChange change in changes.FieldChanges) { if (GetSharingType(change) != sharingType) { continue; } if (change.RemoveField) { if (!fullUpdate) { RemoveField(itemId, change); } } else { switch (sharingType) { case DefaultFieldSharing.SharingType.Shared: WriteSharedField(itemId, change, now, fullUpdate); break; case DefaultFieldSharing.SharingType.Unversioned: WriteUnversionedField(itemId, change, now, fullUpdate); break; case DefaultFieldSharing.SharingType.Versioned: WriteVersionedField(itemId, change, now, fullUpdate); break; } } } } } }
public void ShouldPreserveBaseItemSharedFields(Item item) { var proxy = new ProxyItem(new ItemData(item)); proxy.SharedFields = new[] { new ProxyFieldValue(Guid.Empty, "hello") }; var changes = new ItemChanges(item); var sut = new ItemChangeApplyingItemData(proxy, changes); sut.SharedFields.First().Value.Should().Be("hello"); }
public void OnItemSavedRemote_should_remove_active_configuration_items_from_cache() { this.CheckConfigurationItem( this.provider.OnItemSavedRemote, item => { var itemChanges = new ItemChanges(item); itemChanges.SetFieldValue(item.Fields[FieldIDs.IntegrationConfigData], "changed"); return(new ItemSavedRemoteEventArgs(item, itemChanges)); }); }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { foreach (FieldChange change in changes.FieldChanges) { if (ShouldApplyChangeToDataStore(change)) { SaveChangeToDataStore(change, IDTable.GetKeys(IdTablePrefix, itemDefinition.ID).FirstOrDefault().Key); } } return(base.SaveItem(itemDefinition, changes, context)); }
private static void RaiseItemsChanged() { var change = new ItemsChanged() { Name = "Item", AddedIds = { NextIds() } }; change.UpdatedIds.Add(NextIds().Except(change.AddedIds)); change.RemovedIds.Add(NextIds().Except(change.AddedIds).Except(change.UpdatedIds)); ItemChanges.OnItemsChanged(change); }
public void OnItemSavedRemote_should_remove_child_configuration_folderss_from_cache() { // Act this.CheckFoldersStructure( this.provider.OnItemSavedRemote, item => { var itemChanges = new ItemChanges(item); itemChanges.SetFieldValue(item.Fields[FieldIDs.IntegrationConfigData], "changed"); return(new ItemSavedRemoteEventArgs(item, itemChanges)); }); }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { var sqlProvider = GetSqlProvider(Database); if (!EnsureSqlVersion(itemDefinition, sqlProvider, context)) { return(false); } sqlProvider.SaveItem(itemDefinition, changes, context); return(true); }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (!base.SaveItem(itemDefinition, changes, context)) { return(false); } foreach (var provider in _unicornDataProviders) { provider.SaveItem(itemDefinition, changes, context); } return(true); }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); if (!ShouldExecuteProvider(itemDefinition.ID)) { return(false); } context.Abort(); base.SaveItem(itemDefinition, changes, context); return(true); }
private static void DoBaseTemplateUpdates([NotNull] Item item, ItemChanges itemChanges) { var siteSettings = (DynamicSiteSettingsItem)item; if (itemChanges == null || !itemChanges.IsFieldModified(siteSettings.SiteDefinitionTemplate.Field.InnerField.ID)) { DynamicSiteManager.PublishItemChanges(item); return; } var changedField = itemChanges.FieldChanges[siteSettings.SiteDefinitionTemplate.Field.InnerField.ID]; var oldValue = changedField.OriginalValue; var newValue = changedField.Value; if (oldValue.Equals(newValue)) { return; } if (newValue.IsNullOrEmpty()) { if (item.Fields[changedField.FieldID].ContainsStandardValue) { newValue = item.Fields[changedField.FieldID].GetStandardValue(); } } if (!newValue.IsNullOrEmpty()) { var newTemplateItem = DynamicSiteSettings.GetCurrentDatabase.GetTemplate(new ID(newValue)); if (newTemplateItem != null) { DynamicSiteManager.AddBaseTemplate(newTemplateItem); } } if (oldValue.IsNullOrEmpty()) { return; } var oldTemplateItem = DynamicSiteSettings.GetCurrentDatabase.GetTemplate(new ID(oldValue)); if (oldTemplateItem != null) { DynamicSiteManager.RemoveBaseTemplate(oldTemplateItem); } }
public void Save_ShouldNotSerializeItem_IfNoMeaningfulChanges(Db db, DbItem item) { var target = Substitute.For<ITargetDataStore>(); using (var provider = CreateTestProvider(db.Database, targetDataStore: target)) { db.Add(item); var dbItem = db.GetItem(item.ID); var changes = new ItemChanges(dbItem); provider.SaveItem(CreateTestDefinition(), changes, CreateTestCallContext(db.Database)); target.DidNotReceive().Save(Arg.Any<IItemData>()); } }
private static void TransferSingleItem(Item item, DataProviderWrapper provider, Action<string> callback) { ItemDefinition parentDefinition = null; if (item.Parent != null) { parentDefinition = new ItemDefinition(item.Parent.ID, item.Parent.Name, item.Parent.TemplateID, item.Parent.BranchId); } if (callback != null) { callback(item.Paths.FullPath); } // Create the item in database if (provider.CreateItem(item.ID, item.Name, item.TemplateID, parentDefinition, null)) { foreach (var language in item.Languages) { using (new LanguageSwitcher(language)) { var itemInLanguage = item.Database.GetItem(item.ID); if (itemInLanguage != null) { // Add a version var itemDefinition = provider.GetItemDefinition(itemInLanguage.ID, null); // TODO: Add all version and not just v1 provider.AddVersion(itemDefinition, new VersionUri(language, Version.First), null); // Send the field values to the provider var changes = new ItemChanges(itemInLanguage); foreach (Field field in itemInLanguage.Fields) { changes.FieldChanges[field.ID] = new FieldChange(field, field.Value); } provider.SaveItem(itemDefinition, changes, null); } } } } }
public void Save_ShouldSerializeItem(Db db) { var target = Substitute.For<ITargetDataStore>(); using (var provider = CreateTestProvider(db.Database, targetDataStore: target)) { var fieldId = ID.NewID; var item = new DbItem("Test") { { fieldId, "World" } }; db.Add(item); var dbItem = db.GetItem(item.ID); var changes = new ItemChanges(dbItem); changes.SetFieldValue(dbItem.Fields[fieldId], "Hello", "World"); provider.SaveItem(CreateTestDefinition(), changes, CreateTestCallContext(db.Database)); target.Received().Save(Arg.Any<IItemData>()); } }
public void Save_ShouldRenameItem(Db db) { var target = Substitute.For<ITargetDataStore>(); using (var provider = CreateTestProvider(db.Database, targetDataStore: target)) { var fieldId = ID.NewID; var item = new DbItem("Test") { { fieldId, "World" } }; db.Add(item); var dbItem = db.GetItem(item.ID); var changes = new ItemChanges(dbItem); changes.Properties.Add("name", new PropertyChange("name", "Test", "Test Item")); provider.SaveItem(CreateTestDefinition(), changes, CreateTestCallContext(db.Database)); target.Received().MoveOrRenameItem(Arg.Any<IItemData>(), "/sitecore/content/Test Item"); } }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { var current = Provider.GetItem(itemDefinition.ID.ToGuid()); if (current == null) { return false; } if (changes.HasPropertiesChanged) { current.Name = StringUtil.GetString(changes.GetPropertyValue("name"), itemDefinition.Name); var templateId = MainUtil.GetObject(changes.GetPropertyValue("templateid"), itemDefinition.TemplateID) as ID; current.TemplateId = templateId != ID.Null ? templateId.ToGuid() : Guid.Empty; var branchId = MainUtil.GetObject(changes.GetPropertyValue("branchid"), itemDefinition.BranchId) as ID; current.BranchId = branchId != ID.Null ? branchId.ToGuid() : Guid.Empty; } if (changes.HasFieldsChanged) { foreach (FieldChange change in changes.FieldChanges) { var fieldVersionUri = new VersionUri( change.Definition == null || change.Definition.IsShared ? null : change.Language, change.Definition == null || change.Definition.IsUnversioned ? null : change.Version); var matchingFields = current.FieldValues.Where(fv => fv.Matches(fieldVersionUri) && fv.Id.Equals(change.FieldID.ToGuid())).ToList(); if (change.RemoveField) { if (matchingFields.Any()) { current.FieldValues.Remove(matchingFields.First()); } } else { if (matchingFields.Any()) { current.FieldValues.Find(fv => fv.Matches(fieldVersionUri) && fv.Id.Equals(change.FieldID.ToGuid())).Value = change.Value; } else { current.FieldValues.Add(new FieldDto { Id = change.FieldID.ToGuid(), Language = fieldVersionUri.Language != null ? fieldVersionUri.Language.Name : null, Version = fieldVersionUri.Version != null ? fieldVersionUri.Version.Number : null as int?, Value = change.Value }); } if (change.FieldID == FieldIDs.WorkflowState) { Guid workflowStateId = Guid.Empty; Guid.TryParse(change.Value, out workflowStateId); current.WorkflowStateId = workflowStateId; } } } Provider.WritableProvider.Store(current); } return true; }
public virtual void SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (DisableSerialization) return; Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); // get the item we're saving to evaluate with the predicate // NOTE: the item in this state may be incomplete as Sitecore can sometimes send partial item data and rely on changes to do the save // e.g. during package installations. So we have to merge the changes with any existing item data if we save it later, to keep it consistent. IItemData sourceItem = new ItemData(changes.Item); if (!_predicate.Includes(sourceItem).IsIncluded) return; string oldName = changes.Renamed ? changes.Properties["name"].OriginalValue.ToString() : string.Empty; if (changes.Renamed && !oldName.Equals(sourceItem.Name, StringComparison.Ordinal)) // it's a rename, in which the name actually changed (template builder will cause 'renames' for the same name!!!) { using (new DatabaseCacheDisabler()) { // disabling the DB caches while running this ensures that any children of the renamed item are retrieved with their proper post-rename paths and thus are not saved at their old location // this allows us to filter out any excluded children by predicate when the data store moves children var predicatedItem = new PredicateFilteredItemData(sourceItem, _predicate); _targetDataStore.MoveOrRenameItem(predicatedItem, changes.Item.Paths.ParentPath + "/" + oldName); } _logger.RenamedItem(_targetDataStore.FriendlyName, sourceItem, oldName); } else if (HasConsequentialChanges(changes)) // it's a simple update - but we reject it if only inconsequential fields (last updated, revision) were changed - again, template builder FTW { var existingSerializedItem = _targetDataStore.GetByPathAndId(sourceItem.Path, sourceItem.Id, sourceItem.DatabaseName); // generated an IItemData from the item changes we received, and apply those changes to the existing serialized item if any if (existingSerializedItem != null) sourceItem = new ItemChangeApplyingItemData(existingSerializedItem, changes); else sourceItem = new ItemChangeApplyingItemData(changes); _targetDataStore.Save(sourceItem); AddBlobsToCache(sourceItem); _logger.SavedItem(_targetDataStore.FriendlyName, sourceItem, "Saved"); } }
public ItemChangeApplyingItemVersion(IItemVersion innerVersion, ItemChanges changes) { _innerVersion = innerVersion; _changes = changes; }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); var existingItem = SerializedDatabase.GetItem(itemDefinition.ID); if (existingItem == null) return false; // item was not in this data provider, cede control to the next one var savedItem = ItemSynchronization.BuildSyncItem(changes.Item); if(changes.Renamed) SerializedDatabase.SaveAndRenameItem(savedItem, changes.Properties["name"].OriginalValue.ToString()); else SerializedDatabase.SaveItem(savedItem); return true; }
protected virtual bool HasConsequentialChanges(ItemChanges changes) { // properties, e.g. template, etc are always consequential // NOTE: sometimes you can get spurious 'changes' where the old and new value are the same. We reject those. if (changes.HasPropertiesChanged && changes.Properties.Any(x => !x.Value.OriginalValue.Equals(x.Value.Value))) return true; foreach (FieldChange change in changes.FieldChanges) { if (change.OriginalValue == change.Value) continue; if (change.FieldID == FieldIDs.Revision) continue; if (change.FieldID == FieldIDs.Updated) continue; if (change.FieldID == FieldIDs.UpdatedBy) continue; if (change.FieldID == FieldIDs.Originator) continue; if (!_fieldFilter.Includes(change.FieldID.Guid)) continue; return true; } _logger.SaveRejectedAsInconsequential(_targetDataStore.FriendlyName, changes); return false; }
private bool EnsureSqlVersion(ItemDefinition itemDefinition, DataProvider sqlProvider, CallContext context) { var sqlVersion = GetSqlVersion(itemDefinition.ID, context, sqlProvider); if (sqlVersion != null) { return true; } if (itemDefinition.ID == FolderId || ControllerType.GetAllNamespaces().ContainsKey(itemDefinition.ID.ToGuid()) || ControllerType.GetAllControllers().ContainsKey(itemDefinition.ID.ToGuid()) || ControllerAction.GetControllerAction(itemDefinition.ID) != null) { var parentId = GetParentID(itemDefinition, context) ?? sqlProvider.GetParentID(itemDefinition, context); var itemdef = GetItemDefinition(parentId, context) ?? sqlProvider.GetItemDefinition(parentId, context); if (!sqlProvider.CreateItem(itemDefinition.ID, itemDefinition.Name, itemDefinition.TemplateID, itemdef, context)) { return false; } var item = Database.GetItem(itemDefinition.ID); var existingFields = new ItemChanges(item); foreach (Field field in item.Fields) { existingFields.SetFieldValue(field, item[field.ID]); } sqlProvider.SaveItem(itemDefinition, existingFields, context); return true; } return false; }
public void SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (DisableSerialization) return; Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); var sourceItem = GetItemWithoutCache(changes.Item); if (!_predicate.Includes(sourceItem).IsIncluded) return; string oldName = changes.Renamed ? changes.Properties["name"].OriginalValue.ToString() : string.Empty; if (changes.Renamed && !oldName.Equals(sourceItem.Name, StringComparison.Ordinal)) // it's a rename, in which the name actually changed (template builder will cause 'renames' for the same name!!!) { _serializationProvider.RenameSerializedItem(sourceItem, oldName); _logger.RenamedItem(_serializationProvider.LogName, sourceItem, oldName); } else if (HasConsequentialChanges(changes)) // it's a simple update - but we reject it if only inconsequential fields (last updated, revision) were changed - again, template builder FTW { _serializationProvider.SerializeItem(sourceItem); _logger.SavedItem(_serializationProvider.LogName, sourceItem, "Saved"); } }
/// <summary> /// Save changes that were made to an item to the database. /// </summary> /// <param name="itemDefinition">Used to identify the particular item</param> /// <param name="changes">A holder object that keeps track of the changes</param> /// <param name="context"></param> /// <returns></returns> public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (! ItemsById.ContainsKey(itemDefinition.ID)) { return false; } SyncItem current = ItemsById[itemDefinition.ID]; if (changes.HasPropertiesChanged) { current.Name = StringUtil.GetString(changes.GetPropertyValue("name"), itemDefinition.Name); var templateId = MainUtil.GetObject(changes.GetPropertyValue("templateid"), itemDefinition.TemplateID) as ID; current.TemplateID = templateId != ID.Null ? GetIdAsString(templateId) : null; var branchId = MainUtil.GetObject(changes.GetPropertyValue("branchid"), itemDefinition.BranchId) as ID; current.BranchId = branchId != ID.Null ? GetIdAsString(branchId) : null; } if (changes.HasFieldsChanged) { foreach (FieldChange change in changes.FieldChanges) { string changeFieldId = GetIdAsString(change.FieldID); IEnumerable<SyncField> matchingSharedFields = current.SharedFields.Where(fv => changeFieldId.Equals(fv.FieldID)); IEnumerable<SyncVersion> matchingVersions = current.Versions .Where( vr => vr.Version.Equals(change.Version.Number.ToString()) && vr.Language.Equals(change.Language.Name)); var matchingNonSharedFields = matchingVersions .SelectMany(vr => vr.Fields.Select(fl => new {Ver = vr, Field = fl})) .Where(fv => changeFieldId.Equals(fv.Field.FieldID)); if (change.RemoveField) { if (matchingSharedFields.Any()) { current.SharedFields.Remove(matchingSharedFields.First()); } if (matchingNonSharedFields.Any()) { matchingNonSharedFields.First() .Ver.RemoveField(matchingNonSharedFields.First().Field.FieldName); } } else { bool changeMade = false; if (matchingSharedFields.Any()) { matchingSharedFields.First().FieldValue = change.Value; changeMade = true; } if (matchingNonSharedFields.Any()) { matchingNonSharedFields.First().Field.FieldValue = change.Value; changeMade = true; } if (! changeMade && change.Definition != null) { if (change.Definition.IsShared || change.Definition.IsUnversioned) { current.AddSharedField(changeFieldId, change.Definition.Name, change.Definition.Key, change.Value, true); } else if (matchingVersions.Any()) { matchingVersions.First() .AddField(changeFieldId, change.Definition.Name, change.Definition.Key, change.Value, true); } } } } } return true; }
private void RunItemSaved(Item item, ItemChanges itemChanges) { var db = item.Database; var rulesEngine = new RulesEngine(db); try { using (new SecurityDisabler()) { var redirectFolderItem = item.Axes.GetAncestors() .FirstOrDefault(a => a.TemplateID.Equals(new ID(RedirectFolderItem.TemplateId))); if (redirectFolderItem == null) return; if (item.IsRedirectFolderItem()) { Log.Info(this, db, "Refreshing Redirect Folder [{0}] after save event", item.Paths.FullPath); rulesEngine.GetCachedInboundRules(); } else if (item.IsOutboundRuleItem()) { Log.Info(this, db, "Refreshing Outbound Rule [{0}] after save event", item.Paths.FullPath); rulesEngine.RefreshRule(item, redirectFolderItem); } else if (item.IsSimpleRedirectItem()) { Log.Info(this, db, "Refreshing Simple Redirect [{0}] after save event", item.Paths.FullPath); rulesEngine.RefreshRule(item, redirectFolderItem); } else if (item.IsInboundRuleItem()) { Log.Info(this, db, "Refreshing Inbound Rule [{0}] after save event", item.Paths.FullPath); rulesEngine.RefreshRule(item, redirectFolderItem); } else if (item.IsRedirectType() && item.IsInboundRuleItemChild() && db.Name.Equals("master", StringComparison.CurrentCultureIgnoreCase)) { var inboundRuleItem = item.Parent; var inboundRule = new InboundRuleItem(inboundRuleItem); inboundRule.BeginEdit(); inboundRule.Action.InnerField.SetValue(item.ID.ToString(), false); inboundRule.EndEdit(); } else if (item.IsInboundRuleItemChild()) { Log.Info(this, db, "Refreshing Inbound Rule [{0}] after save event", item.Parent.Paths.FullPath); rulesEngine.RefreshRule(item.Parent, redirectFolderItem); } else if (item.IsOutboundRuleItemChild()) { Log.Info(this, db, "Refreshing Outbound Rule [{0}] after save event", item.Parent.Paths.FullPath); rulesEngine.RefreshRule(item.Parent, redirectFolderItem); } } } catch (Exception ex) { Log.Error(this, ex, db, "Exception occured when saving item after save - Item ID: {0} Item Path: {1}", item.ID, item.Paths.FullPath); } }
public bool SaveItem(ID itemID, ItemChanges changes) { Assert.ArgumentNotNull(itemID, nameof(itemID)); Assert.ArgumentNotNull(changes, nameof(changes)); var item = this.GetItem(itemID); if (item == null) { return false; } if (this.ReadOnly) { throw new InvalidOperationException($"The file mapping the {itemID} item belongs to is in read-only mode"); } Lock.EnterWriteLock(); try { if (changes.HasPropertiesChanged) { var name = changes.GetPropertyValue("name") as string; item.Name = name ?? item.Name; var templateID = changes.GetPropertyValue("templateid") as ID; item.TemplateID = templateID ?? item.TemplateID; } if (changes.HasFieldsChanged) { var saveAll = changes.Item.RuntimeSettings.SaveAll; if (saveAll) { item.Fields.Shared.Clear(); item.Fields.Unversioned.Clear(); item.Fields.Versioned.Clear(); } foreach (var fieldChange in changes.FieldChanges.OfType<FieldChange>()) { var language = fieldChange.Language; var number = fieldChange.Version.Number; var fieldID = fieldChange.FieldID; if (fieldID == Null.Object) { continue; } var definition = fieldChange.Definition; if (definition == null) { continue; } var value = fieldChange.Value; var shared = item.Fields.Shared; var unversioned = item.Fields.Unversioned[language]; var versions = item.Fields.Versioned[language]; var versioned = versions[number]; if (fieldChange.RemoveField || value == null) { if (saveAll) { continue; } shared.Remove(fieldID); unversioned.Remove(fieldID); versioned?.Remove(fieldID); } else if (definition.IsShared) { shared[fieldID] = value; } else if (definition.IsUnversioned) { unversioned[fieldID] = value; } else if (definition.IsVersioned) { if (versioned == null) { versioned = new JsonFieldsCollection { [FieldIDs.Created] = DateUtil.IsoNowWithTicks }; versions.Add(number, versioned); } versioned[fieldID] = value; } else { throw new NotSupportedException("This situation is not supported"); } } } } finally { Lock.ExitWriteLock(); } this.Commit(); return true; }
/// <summary> /// Saves an item. /// </summary> /// <param name="itemDefinition">The item definition.</param> /// <param name="changes">The changes.</param> /// <param name="context">The context.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { return false; }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); if (!ShouldExecuteProvider(itemDefinition.ID)) return false; context.Abort(); base.SaveItem(itemDefinition, changes, context); return true; }
private static void DoBaseTemplateUpdates([NotNull] Item item, ItemChanges itemChanges) { var siteSettings = (DynamicSiteSettingsItem)item; if (itemChanges == null || !itemChanges.IsFieldModified(siteSettings.SiteDefinitionTemplate.Field.InnerField.ID)) { DynamicSiteManager.PublishItemChanges(item); return; } var changedField = itemChanges.FieldChanges[siteSettings.SiteDefinitionTemplate.Field.InnerField.ID]; var oldValue = changedField.OriginalValue; var newValue = changedField.Value; if (oldValue.Equals(newValue)) return; if (newValue.IsNullOrEmpty()) { if (item.Fields[changedField.FieldID].ContainsStandardValue) { newValue = item.Fields[changedField.FieldID].GetStandardValue(); } } if (!newValue.IsNullOrEmpty()) { var newTemplateItem = DynamicSiteSettings.GetCurrentDatabase.GetTemplate(new ID(newValue)); if (newTemplateItem != null) DynamicSiteManager.AddBaseTemplate(newTemplateItem); } if (oldValue.IsNullOrEmpty()) return; var oldTemplateItem = DynamicSiteSettings.GetCurrentDatabase.GetTemplate(new ID(oldValue)); if (oldTemplateItem != null) DynamicSiteManager.RemoveBaseTemplate(oldTemplateItem); }
public virtual void SaveRejectedAsInconsequential(string providerName, ItemChanges changes) { _logger.Debug(string.Format("{0}: Ignored save of {1} because it contained no consequential item changes.", providerName, changes.Item.Paths.Path)); }
public ItemChangeApplyingItemData(IItemData existingItem, ItemChanges changes) : base(existingItem) { _changes = changes; }
public void SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { if (DisableSerialization) return; Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); Assert.ArgumentNotNull(changes, "changes"); var sourceItem = GetSourceFromId(changes.Item.ID); if (sourceItem == null) return; if (!_predicate.Includes(sourceItem).IsIncluded) return; string oldName = changes.Renamed ? changes.Properties["name"].OriginalValue.ToString() : string.Empty; if (changes.Renamed && !oldName.Equals(sourceItem.Name, StringComparison.Ordinal)) // it's a rename, in which the name actually changed (template builder will cause 'renames' for the same name!!!) { using (new DatabaseCacheDisabler()) { // disabling the DB caches while running this ensures that any children of the renamed item are retrieved with their proper post-rename paths and thus are not saved at their old location // this allows us to filter out any excluded children by predicate when the data store moves children var predicatedItem = new PredicateFilteredItemData(sourceItem, _predicate); _targetDataStore.MoveOrRenameItem(predicatedItem, changes.Item.Paths.ParentPath + "/" + oldName); } _logger.RenamedItem(_targetDataStore.FriendlyName, sourceItem, oldName); } else if (HasConsequentialChanges(changes)) // it's a simple update - but we reject it if only inconsequential fields (last updated, revision) were changed - again, template builder FTW { _targetDataStore.Save(sourceItem); AddBlobsToCache(sourceItem); _logger.SavedItem(_targetDataStore.FriendlyName, sourceItem, "Saved"); } }
public override bool SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context) { var sqlProvider = GetSqlProvider(Database); if (!EnsureSqlVersion(itemDefinition, sqlProvider, context)) return false; sqlProvider.SaveItem(itemDefinition, changes, context); return true; }
protected virtual bool HasConsequentialChanges(ItemChanges changes) { // properties, e.g. template, etc are always consequential // NOTE: sometimes you can get spurious 'changes' where the old and new value are the same. We reject those. if (changes.HasPropertiesChanged && changes.Properties.Any(x => !x.Value.OriginalValue.Equals(x.Value.Value))) return true; foreach (FieldChange change in changes.FieldChanges) { // NOTE: we do not check for old and new value equality here // because during package installation Sitecore will set item fields using // identical old and new values in the changes - for fields that have never been set before. if (change.FieldID == FieldIDs.Revision) continue; if (change.FieldID == FieldIDs.Updated) continue; if (change.FieldID == FieldIDs.UpdatedBy) continue; if (change.FieldID == FieldIDs.Originator) continue; if (!_fieldFilter.Includes(change.FieldID.Guid)) continue; return true; } _logger.SaveRejectedAsInconsequential(_targetDataStore.FriendlyName, changes); return false; }
public ItemChangeApplyingItemData(ItemChanges changes) : base(new ProxyItem(changes.Item.Name, changes.Item.ID.Guid, changes.Item.ParentID.Guid, changes.Item.TemplateID.Guid, changes.Item.Paths.Path, changes.Item.Database.Name)) { _changes = changes; }
private bool HasValidChanges(ItemChanges changes) { foreach (FieldChange change in changes.FieldChanges) { if(change.OriginalValue == change.Value) continue; if (change.FieldID == FieldIDs.Revision) continue; if (change.FieldID == FieldIDs.Updated) continue; return true; } Log.Info("Item " + changes.Item.Paths.FullPath + " was saved, but contained no consequential changes so it was not serialized.", this); return false; }
protected virtual bool HasConsequentialChanges(ItemChanges changes) { // properties, e.g. template, etc are always consequential if (changes.HasPropertiesChanged) return true; foreach (FieldChange change in changes.FieldChanges) { if (change.OriginalValue == change.Value) continue; if (change.FieldID == FieldIDs.Revision) continue; if (change.FieldID == FieldIDs.Updated) continue; if (!_fieldPredicate.Includes(change.FieldID).IsIncluded) continue; return true; } _logger.SaveRejectedAsInconsequential(_serializationProvider.LogName, changes); return false; }