public void ShouldRebasePathOfChildren() { var root = new FakeItem(children: new[] { new FakeItem() }, id: Guid.NewGuid()); var rebase = new PathRebasingProxyItem(root, "/sitecore/new", Guid.NewGuid()); rebase.GetChildren().First().Path.Should().Be("/sitecore/new/test item/test item"); rebase.GetChildren().First().ParentId.Should().Be(root.Id); }
public void ShouldRebasePath() { var root = new FakeItem(); var pid = Guid.NewGuid(); var rebase = new PathRebasingProxyItem(root, "/sitecore/new", pid); rebase.Path.Should().Be("/sitecore/new/test item"); rebase.ParentId.Should().Be(pid); }
public virtual 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 } // rebase the path to the new destination path (this handles children too) var rebasedSourceItem = new PathRebasingProxyItem(sourceItem, destinationItem.Path, destinationItem.Id); if (!_predicate.Includes(rebasedSourceItem).IsIncluded) { // if the destination we are moving to is NOT included for serialization, we delete the existing item from serialization var existingItem = _targetDataStore.GetByPathAndId(sourceItem.Path, sourceItem.Id, sourceItem.DatabaseName); if (existingItem != null) { _targetDataStore.Remove(existingItem); _logger.MovedItemToNonIncludedLocation(_targetDataStore.FriendlyName, existingItem); } return; } // 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); }
/* * Moving an item involves: * - Get the item from the tree, delete * - If the new path is included in ANY tree * - Get the serialized parent at the destination * - Get the moved tree from Sitecore, save whole tree (NOTE: we had to update to final path in DP - what about children are those with old or new path?) * * Renaming an item involves: * - The same thing as moving an item */ public virtual void MoveOrRenameItem(IItemData itemWithFinalPath, string oldPath) { // GET EXISTING ITEM WE'RE MOVING + DESCENDANT PATHS var oldPathTree = GetTreeForPath(oldPath, itemWithFinalPath.DatabaseName); Dictionary <string, IItemMetadata> oldPathItemAndDescendants; var oldPathItem = oldPathTree?.GetItemsByPath(oldPath).FirstOrDefault(item => item.Id == itemWithFinalPath.Id); if (oldPathItem != null) { oldPathItemAndDescendants = oldPathTree.GetDescendants(oldPathItem, false).ToDictionary(item => item.SerializedItemId); oldPathItemAndDescendants.Add(oldPathItem.SerializedItemId, oldPathItem); } else { oldPathItemAndDescendants = new Dictionary <string, IItemMetadata>(); } // WRITE THE NEW MOVED/RENAMED ITEMS TO THE TREE (note: delete goes last because with TpSync we need the old items to read from) var newPathTree = GetTreeForPath(itemWithFinalPath.Path, itemWithFinalPath.DatabaseName); // force consistency of parent IDs and paths among child items before we serialize them var rebasedPathItem = new PathRebasingProxyItem(itemWithFinalPath); // add new tree, if it's included (if it's moving to a non included path we simply delete it and are done) if (newPathTree != null) { var saveQueue = new Queue <IItemData>(); saveQueue.Enqueue(rebasedPathItem); while (saveQueue.Count > 0) { var parent = saveQueue.Dequeue(); var tree = GetTreeForPath(parent.Path, parent.DatabaseName); if (tree == null) { throw new InvalidOperationException("No trees contained the global path " + parent.Path); } using (new SfsDuplicateIdCheckingDisabler()) { var savedPath = tree.Save(parent); // if we saved an item that was a former child of the item we want to keep it when we're doing deletions if (oldPathItemAndDescendants.ContainsKey(savedPath)) { oldPathItemAndDescendants.Remove(savedPath); } } var children = parent.GetChildren(); foreach (var child in children) { saveQueue.Enqueue(child); } } } // in case an item was renamed by case or someone calls rename without renaming, we don't want to delete anything // 'cause that'd just delete the item, not move it :) if (oldPath.Equals(itemWithFinalPath.Path, StringComparison.OrdinalIgnoreCase)) { return; } // REMOVE EXISTING ITEMS (if any) // (excluding any items that we wrote to during the save phase above, e.g. loopback path items may not change during a move) if (oldPathTree != null) { var oldItems = oldPathItemAndDescendants .Select(key => key.Value) .OrderByDescending(item => item.Path) .ToArray(); foreach (var item in oldItems) { oldPathTree.RemoveWithoutChildren(item); } } }