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 void MoveItem(ItemDefinition itemDefinition, ItemDefinition destination, CallContext context) { if (DisableSerialization) { return; } Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); var oldSourceItem = GetSourceFromId(itemDefinition.ID, true); // we use cache here because we want the old path var oldPath = oldSourceItem.Path; // NOTE: we cap the path here, because once we enter the cache-disabled section - to get the new paths for parent and children - the path cache updates and the old path is lost in oldSourceItem because it is reevaluated each time. var destinationItem = GetSourceFromId(destination.ID); if (!_predicate.Includes(destinationItem).IsIncluded) // if the destination we are moving to is NOT included for serialization, we delete the existing item { var existingItem = _targetDataStore.GetByPathAndId(oldSourceItem.Path, oldSourceItem.Id, oldSourceItem.DatabaseName); if (existingItem != null) { _targetDataStore.Remove(existingItem); _logger.MovedItemToNonIncludedLocation(_targetDataStore.FriendlyName, existingItem); } return; } using (new DatabaseCacheDisabler()) { // disabling the DB caches while running this ensures that any children of the moved item are retrieved with their proper post-rename paths and thus are not saved at their old location var sourceItem = GetSourceFromId(itemDefinition.ID); // re-get the item with cache disabled // 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, oldPath); _logger.MovedItem(_targetDataStore.FriendlyName, sourceItem, destinationItem); } }
public void MoveItem(ItemDefinition itemDefinition, ItemDefinition destination, CallContext context) { if (DisableSerialization) { return; } Assert.ArgumentNotNull(itemDefinition, "itemDefinition"); var sourceItem = GetSourceFromId(itemDefinition.ID, true); // we use cache here because we want the old path (no cache would have the new path); TpSync always has old path var oldPath = sourceItem.Path; // NOTE: we cap the path here, because Sitecore can change the item's path value as we're updating stuff. var destinationItem = GetSourceFromId(destination.ID); if (destinationItem == null) { return; // can occur with TpSync on, when this isn't the configuration we're moving for the data store will return null } if (!_predicate.Includes(destinationItem).IsIncluded) // if the destination we are moving to is NOT included for serialization, we delete the existing item { var existingItem = _targetDataStore.GetByPathAndId(sourceItem.Path, sourceItem.Id, sourceItem.DatabaseName); if (existingItem != null) { _targetDataStore.Remove(existingItem); _logger.MovedItemToNonIncludedLocation(_targetDataStore.FriendlyName, existingItem); } return; } // rebase the path to the new destination path (this handles children too) var rebasedSourceItem = new PathRebasingItemData(sourceItem, destinationItem.Path, destinationItem.Id); // this allows us to filter out any excluded children by predicate when the data store moves children var predicatedItem = new PredicateFilteredItemData(rebasedSourceItem, _predicate); _targetDataStore.MoveOrRenameItem(predicatedItem, oldPath); _logger.MovedItem(_targetDataStore.FriendlyName, predicatedItem, destinationItem); }
public override Warning EvaluateEditorWarning(Item item, PredicateResult predicateResult) { bool transparentSync = item.Statistics.UpdatedBy == UnicornDataProvider.TransparentSyncUpdatedByValue; string title = transparentSync ? "This item is included by Unicorn Transparent Sync" : "This item is controlled by Unicorn"; var message = new StringBuilder(); if (IsDevMode) { message.Append("Changes to this item will be written to disk so they can be shared with others."); } else { message.Append("<b style=\"color: red; font-size: 24px;\">You should not change this item because your changes will be overwritten by the next code deployment.</b><br>Ask a developer for help if you need to change this item."); } message.Append($"<br><br><b>Configuration</b>: {_parentConfiguration.Name}"); if (predicateResult.PredicateComponentId != null) { message.Append($"<br><b>Predicate Component</b>: {predicateResult.PredicateComponentId}"); } if (transparentSync) { using (new TransparentSyncDisabler()) { using (new DatabaseCacheDisabler()) { var dbItem = Database.GetItem(item.Uri); if (dbItem != null) { message.Append("<br><b>Transparent Sync</b>: Database + Serialized"); } else { message.Append("<br><b>Transparent Sync</b>: Serialized Only"); } } } } var existingTargetItem = _targetDataStore.GetByPathAndId(item.Paths.Path, item.ID.Guid, item.Database.Name); // check if serialized item ID looks like a filesystem path e.g. c:\ if (IsDevMode && existingTargetItem?.SerializedItemId != null && existingTargetItem.SerializedItemId.Substring(1, 2) == ":\\") { message.Append($"<br><b>Physical path</b>: <span style=\"font-family: consolas, monospace\">{existingTargetItem.SerializedItemId}</span>"); } return(new Warning(title, message.ToString())); }
public virtual Warning EvaluateEditorWarning(Item item) { // if dev mode is on, we don't need a warning if (Settings.GetBoolSetting("Unicorn.DevMode", true)) { return(new Warning("This item is part of a Unicorn deploy once configuration", "Changes to this item will not be synced to other environments unless the item needs to be created.")); } var existingTargetItem = _targetDataStore.GetByPathAndId(item.Paths.Path, item.ID.Guid, item.Database.Name); // if we have no existing serialized item, there's no need for a warning: Unicorn won't touch this item when using NIO if (existingTargetItem == null) { return(null); } return(new Warning("This item was created by Unicorn", "You may edit this item, but deleting it may result in its return next time code is deployed. Ask a developer to help if you need to delete this item.")); }
public virtual Warning EvaluateEditorWarning(Item item, PredicateResult predicateResult) { var existingTargetItem = _targetDataStore.GetByPathAndId(item.Paths.Path, item.ID.Guid, item.Database.Name); // if we have no existing serialized item, there's no need for a warning: Unicorn won't touch this item when using NIO if (existingTargetItem == null) { return(null); } var title = "This item is part of a Unicorn deploy once configuration."; var message = new StringBuilder(); // if dev mode is on, we don't need a warning if (IsDevMode) { message.Append("Changes to this item will not be synced to other environments unless the item does not exist yet."); } else { title = "This item was added by developers."; message.Append("You may edit this item, but <b>it will return next time code is deployed</b>. Ask a developer to help if you need to delete this item."); } message.Append($"<br><br><b>Configuration</b>: {_parentConfiguration.Name}"); if (predicateResult.PredicateComponentId != null) { message.Append($"<br><b>Predicate Component</b>: {predicateResult.PredicateComponentId}"); } // check if serialized item ID looks like a filesystem path e.g. c:\ if (IsDevMode && existingTargetItem?.SerializedItemId != null && existingTargetItem.SerializedItemId.Substring(1, 2) == ":\\") { message.Append($"<br><b>Physical path</b>: <span style=\"font-family: consolas, monospace\">{existingTargetItem.SerializedItemId}</span>"); } return(new Warning(title, message.ToString())); }