protected virtual void UpdateSerializedItem(ISerializedItem serializedItem) { var typed = serializedItem as SitecoreSerializedItem; if (typed == null) { throw new ArgumentException("Serialized item must be a SitecoreSerializedItem", "serializedItem"); } // create any requisite parent folder(s) for the serialized item var parentPath = Directory.GetParent(SerializationPathUtility.GetReferenceDirectoryPath(serializedItem)); if (parentPath != null && !parentPath.Exists) { Directory.CreateDirectory(parentPath.FullName); } // if the file already exists, delete it. Why? Because the FS is case-insensitive, if an item is renamed by case only it won't actually rename // on the filesystem. Deleting it first makes sure this occurs. if (File.Exists(serializedItem.ProviderId)) { File.Delete(serializedItem.ProviderId); } using (var fileStream = File.Open(serializedItem.ProviderId, FileMode.Create, FileAccess.Write, FileShare.None)) { using (var writer = new StreamWriter(fileStream)) { typed.InnerItem.Serialize(writer); } } }
public virtual ISerializedItem[] GetChildItems(ISerializedReference parent) { Assert.ArgumentNotNull(parent, "parent"); var path = SerializationPathUtility.GetReferenceDirectoryPath(parent); var shortPath = SerializationPathUtility.GetShortSerializedReferencePath(_rootPath, parent); var fileNames = new List <string>(); bool longPathExists = Directory.Exists(path); bool shortPathExists = Directory.Exists(shortPath); if (!longPathExists && !shortPathExists) { return(new ISerializedItem[0]); } if (longPathExists) { fileNames.AddRange(Directory.GetFiles(path, "*" + PathUtils.Extension)); } if (shortPathExists) { fileNames.AddRange(Directory.GetFiles(shortPath, "*" + PathUtils.Extension)); } return(fileNames.Select(ReadItemFromDisk).ToArray()); }
protected virtual void DeleteItemRecursive(ISerializedReference reference) { foreach (var child in reference.GetChildReferences(false)) { DeleteItemRecursive(child); } // kill the serialized file var fileItem = reference.GetItem(); if (fileItem != null && File.Exists(fileItem.ProviderId)) { File.Delete(fileItem.ProviderId); } // remove any serialized children var directory = SerializationPathUtility.GetReferenceDirectoryPath(reference); if (Directory.Exists(directory)) { Directory.Delete(directory, true); } // clean up any hashpaths for this item var shortDirectory = SerializationPathUtility.GetShortSerializedReferencePath(_rootPath, reference); if (Directory.Exists(shortDirectory)) { Directory.Delete(shortDirectory, true); } // clean up empty parent folder(s) var parentDirectory = Directory.GetParent(directory); if (!parentDirectory.Exists) { return; } do { if (parentDirectory.GetFileSystemInfos().Length > 0) { break; } parentDirectory.Delete(true); parentDirectory = parentDirectory.Parent; } while (parentDirectory != null && parentDirectory.Exists); }
/// <summary> /// Moves the descendant items of a serialized parent after it has been moved or renamed. /// </summary> /// <param name="oldReference">Reference to the original path pre-move/rename</param> /// <param name="newItem">The newly renamed or moved parent item</param> /// <param name="sourceItem">The source item representing the renamed/moved item. NOTE that the path of this item is incorrect a lot of the time so we ignore it.</param> /// <param name="renaming">True for moving renamed children, false for moving moved children. For renames, the children already have correct new paths; for moves we have to recalculate it.</param> /// <remarks> /// This method basically gets all descendants of the source item that was moved/renamed, generates an appropriate new serialized item for it, and _if the new child item is in the predicate_ we /// serialize it to its new location. Finally, we delete the old children directory if it existed. /// /// Doing it this way allows handling crazy cases like moving trees of items between included and excluded locations - or even moves or renames causing SOME of the children to be ignored. Wild. /// </remarks> protected virtual void MoveDescendants(ISerializedReference oldReference, ISerializedItem newItem, ISourceItem sourceItem, bool renaming) { // remove the extension from the new item's provider ID string newItemReferencePath = SerializationPathUtility.GetReferenceDirectoryPath(newItem); // if the paths were the same, no moving occurs (this can happen when saving templates, which spuriously can report "renamed" when they are not actually any such thing) if (oldReference.ProviderId.Equals(newItemReferencePath, StringComparison.Ordinal)) { return; } // this is for renaming an item that differs only by case from the original. Because NTFS is case-insensitive the 'new parent' exists // already, but it will use the old name. Not quite what we want. So we need to manually rename the folder. if (oldReference.ProviderId.Equals(newItemReferencePath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(oldReference.ProviderId)) { Directory.Move(oldReference.ProviderId, oldReference.ProviderId + "_tempunicorn"); Directory.Move(oldReference.ProviderId + "_tempunicorn", newItemReferencePath); } var descendantItems = GetDescendants(sourceItem).Cast <SitecoreSourceItem>(); // Go through descendant source items and serialize all that are included by the predicate foreach (var descendant in descendantItems) { var syncItem = ItemSynchronization.BuildSyncItem(descendant.InnerItem); // the newPhysicalPath will point to the OLD physical path pre-move (but for renames we actually get the new path already). // For moves, we re-root the path to point to the new parent item's base path to fix that before we write to disk string newItemPath = (renaming) ? descendant.ItemPath : descendant.ItemPath.Replace(oldReference.ItemPath, newItem.ItemPath); var newPhysicalPath = SerializationPathUtility.GetSerializedItemPath(_rootPath, syncItem.DatabaseName, newItemPath); var newSerializedItem = new SitecoreSerializedItem(syncItem, newPhysicalPath, this); if (!_predicate.Includes(newSerializedItem).IsIncluded) { continue; // if the moved child location is outside the predicate, do not re-serialize } UpdateSerializedItem(newSerializedItem); } // remove the old children folder if it exists - as long as the original name was not a case insensitive version of this item if (Directory.Exists(oldReference.ProviderId) && !oldReference.ProviderId.Equals(newItemReferencePath, StringComparison.OrdinalIgnoreCase)) { Directory.Delete(oldReference.ProviderId, true); } }
public virtual ISerializedReference[] GetChildReferences(ISerializedReference parent, bool recursive) { Assert.ArgumentNotNull(parent, "parent"); var longPath = SerializationPathUtility.GetReferenceDirectoryPath(parent); var shortPath = SerializationPathUtility.GetShortSerializedReferencePath(_rootPath, parent); Func <string, string[]> parseDirectory = path => { if (!Directory.Exists(path)) { return(new string[0]); } var resultSet = new HashSet <string>(); try { string[] files = Directory.GetFiles(path, "*" + PathUtils.Extension); foreach (var file in files) { resultSet.Add(file); } string[] directories = SerializationPathUtility.GetDirectories(path, this); // add directories that aren't already ref'd indirectly by a file foreach (var directory in directories) { if (CommonUtils.IsDirectoryHidden(directory)) { continue; } if (!resultSet.Contains(directory + PathUtils.Extension)) { resultSet.Add(directory); } } string[] resultArray = resultSet.ToArray(); // make sure if a "templates" item exists in the current set, it goes first if (resultArray.Length > 1) { for (int i = 1; i < resultArray.Length; i++) { if ("templates".Equals(Path.GetFileName(resultArray[i]), StringComparison.OrdinalIgnoreCase)) { string text = resultArray[0]; resultArray[0] = resultArray[i]; resultArray[i] = text; } } } return(resultArray); } catch (DirectoryNotFoundException) { // it seems like occasionally, even though we use Directory.Exists() to make sure the parent dir exists, that when we actually call Directory.GetFiles() // it throws an error that the directory does not exist during recursive deletes. If the directory does not exist, then we can safely assume no children are present. return(new string[0]); } }; var results = Enumerable.Concat(parseDirectory(longPath), parseDirectory(shortPath)); List <ISerializedReference> referenceResults = results.Select(x => (ISerializedReference) new SitecoreSerializedReference(x, this)).ToList(); if (recursive) { var localReferenceResults = referenceResults.ToArray(); foreach (var child in localReferenceResults) { referenceResults.AddRange(GetChildReferences(child, true)); } } return(referenceResults.ToArray()); }