diff --git a/uSync8.ContentEdition/Serializers/ContentSerializerBase.cs b/uSync8.ContentEdition/Serializers/ContentSerializerBase.cs index ee8f671d..1ee2f8b3 100644 --- a/uSync8.ContentEdition/Serializers/ContentSerializerBase.cs +++ b/uSync8.ContentEdition/Serializers/ContentSerializerBase.cs @@ -32,8 +32,8 @@ public abstract class ContentSerializerBase : SyncTreeSerializerBase pathCache; // not thread safe ?? - protected Dictionary pathCache; protected Dictionary> nameCache; + protected Dictionary pathCache; protected string relationAlias; @@ -631,41 +631,53 @@ protected override Attempt FindOrCreate(XElement node) protected override string GetItemBaseType(XElement node) => node.Name.LocalName; - public virtual string GetItemPath(TObject item) + public virtual string GetItemPath(TObject item) => GetFriendlyPath(item.Path); + + /// + /// Get the friendly path for an item, leaning on our internal cache + /// as best we can. + /// + /// + /// The path is a list of ids, e.g -1,1024,1892,2094,4811 + /// + /// for speed we cache path lookups so we don't have to do them again, + /// (e.g -1,1024,1892) - + /// + /// so when we get a path from a node, we want to find the largest + /// string of ids that is cached, and then we will have to lookup + /// the remainder, + /// + /// we use to do this by recursing down, but entityService.GetAll is + /// faster then individual calls to Get - so its quicker to do it + /// in a batch, as long as we don't ask for the ones we already know + /// about. + /// + private string GetFriendlyPath(string path) { - if (pathCache.ContainsKey(item.Path)) return pathCache[item.Path]; + var ids = path.ToDelimitedList().Select(x => int.Parse(x)); + var lookups = new List(); + var friendlyPath = ""; - if (item.Trashed) + foreach(var id in ids) { - var parent = GetTrashedParent(item); - if (parent != null) + if (!nameCache.ContainsKey(id)) + { + lookups.Add(id); + } + else { - return GetItemPath(parent) + "/" + item.Name.ToSafeAlias(); + friendlyPath += "/" + nameCache[id].Item2.ToSafeAlias(); } } - var entity = entityService.Get(item.Id); - if (entity != null) - return GetItemPath(entity); - - return ""; - } - - protected virtual string GetItemPath(IEntitySlim item) - { - // path caching, stops us looking up the same path all the time. - if (pathCache.ContainsKey(item.Path)) return pathCache[item.Path]; - - var path = ""; - if (item.ParentId != -1) + var items = entityService.GetAll(this.umbracoObjectType, lookups.ToArray()); + foreach(var item in items) { - var parent = entityService.Get(item.ParentId); - if (parent != null) - path += GetItemPath(parent); + nameCache[item.Id] = new Tuple(item.Key, item.Name); + friendlyPath += "/" + item.Name.ToSafeAlias(); } - pathCache[item.Path] = path + "/" + item.Name.ToSafeAlias(); - return pathCache[item.Path]; + return friendlyPath; } public override SyncAttempt SerializeEmpty(TObject item, SyncActionType change, string alias) @@ -849,9 +861,6 @@ protected override bool HasParentItem(XElement node) private void CleanCaches(int id) { - // clear the path cache of anything with this id. - pathCache.RemoveAll(x => x.Key.Contains(id.ToString())); - // clean the name cache for this id. nameCache.Remove(id); } diff --git a/uSync8.ContentEdition/Serializers/ContentTemplateSerializer.cs b/uSync8.ContentEdition/Serializers/ContentTemplateSerializer.cs index 81b12939..046fd17a 100644 --- a/uSync8.ContentEdition/Serializers/ContentTemplateSerializer.cs +++ b/uSync8.ContentEdition/Serializers/ContentTemplateSerializer.cs @@ -107,6 +107,9 @@ protected override IContent FindItem(Guid key) return null; } + public override string GetItemPath(IContent item) + => base.GetItemPath(item) + "/" + item.Name.ToSafeAlias(); + protected override IContent FindItem(int id) => contentService.GetBlueprintById(id);