|
6 | 6 | using System.Net.Http.Formatting;
|
7 | 7 | using System.Web.Http;
|
8 | 8 | using Umbraco.Core;
|
| 9 | +using Umbraco.Core.Logging; |
9 | 10 | using Umbraco.Core.Models;
|
10 | 11 | using Umbraco.Core.Models.EntityBase;
|
11 | 12 | using Umbraco.Core.Persistence;
|
@@ -69,7 +70,51 @@ public TreeNode GetTreeNode(string id, FormDataCollection queryStrings)
|
69 | 70 | /// </summary>
|
70 | 71 | protected abstract int UserStartNode { get; }
|
71 | 72 |
|
72 |
| - protected abstract TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings); |
| 73 | + /// <summary> |
| 74 | + /// Gets the tree nodes for the given id |
| 75 | + /// </summary> |
| 76 | + /// <param name="id"></param> |
| 77 | + /// <param name="queryStrings"></param> |
| 78 | + /// <returns></returns> |
| 79 | + protected virtual TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings) |
| 80 | + { |
| 81 | + var nodes = new TreeNodeCollection(); |
| 82 | + |
| 83 | + var altStartId = string.Empty; |
| 84 | + if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId)) |
| 85 | + altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId); |
| 86 | + |
| 87 | + //check if a request has been made to render from a specific start node |
| 88 | + if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.Root.ToString(CultureInfo.InvariantCulture)) |
| 89 | + { |
| 90 | + id = altStartId; |
| 91 | + |
| 92 | + //we need to verify that the user has access to view this node, otherwise we'll render an empty tree collection |
| 93 | + // TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access |
| 94 | + if (HasPathAccess(id, queryStrings) == false) |
| 95 | + { |
| 96 | + LogHelper.Warn<ContentTreeControllerBase>("The user " + Security.CurrentUser.Username + " does not have access to the tree node " + id); |
| 97 | + return new TreeNodeCollection(); |
| 98 | + } |
| 99 | + |
| 100 | + // So there's an alt id specified, it's not the root node and the user has access to it, great! But there's one thing we |
| 101 | + // need to consider: |
| 102 | + // If the tree is being rendered in a dialog view we want to render only the children of the specified id, but |
| 103 | + // when the tree is being rendered normally in a section and the current user's start node is not -1, then |
| 104 | + // we want to include their start node in the tree as well. |
| 105 | + // Therefore, in the latter case, we want to change the id to -1 since we want to render the current user's root node |
| 106 | + // and the GetChildEntities method will take care of rendering the correct root node. |
| 107 | + // If it is in dialog mode, then we don't need to change anything and the children will just render as per normal. |
| 108 | + if (IsDialog(queryStrings) == false && UserStartNode != Constants.System.Root) |
| 109 | + { |
| 110 | + id = Constants.System.Root.ToString(CultureInfo.InvariantCulture); |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + var entities = GetChildEntities(id); |
| 115 | + nodes.AddRange(entities.Select(entity => GetSingleTreeNode(entity, id, queryStrings)).Where(node => node != null)); |
| 116 | + return nodes; |
| 117 | + } |
73 | 118 |
|
74 | 119 | protected abstract MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings);
|
75 | 120 |
|
@@ -108,59 +153,44 @@ protected IEnumerable<IUmbracoEntity> GetChildEntities(string id)
|
108 | 153 | protected abstract bool HasPathAccess(string id, FormDataCollection queryStrings);
|
109 | 154 |
|
110 | 155 | /// <summary>
|
111 |
| - /// This will automatically check if the recycle bin needs to be rendered (i.e. its the first level) |
112 |
| - /// and will automatically append it to the result of GetChildNodes. |
| 156 | + /// Ensures the recycle bin is appended when required (i.e. user has access to the root and it's not in dialog mode) |
113 | 157 | /// </summary>
|
114 | 158 | /// <param name="id"></param>
|
115 | 159 | /// <param name="queryStrings"></param>
|
116 | 160 | /// <returns></returns>
|
| 161 | + /// <remarks> |
| 162 | + /// This method is overwritten strictly to render the recycle bin, it should serve no other purpose |
| 163 | + /// </remarks> |
117 | 164 | protected sealed override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
|
118 | 165 | {
|
119 | 166 | //check if we're rendering the root
|
120 |
| - if (id == Constants.System.Root.ToInvariantString()) |
| 167 | + if (id == Constants.System.Root.ToInvariantString() && UserStartNode == Constants.System.Root) |
121 | 168 | {
|
122 |
| - //when rendering the root, 3 things can happen: |
123 |
| - //1. we return -1 children without modifications |
124 |
| - //2. the user has a non -1 content root set and we return that |
125 |
| - //3. the tree has a non -1 content root set and we return that - if the user has access to it. |
| 169 | + var altStartId = string.Empty; |
126 | 170 |
|
127 |
| - var hasUserRoot = UserStartNode != Constants.System.Root; |
128 |
| - var hasTreeRoot = queryStrings.HasKey(TreeQueryStringParameters.StartNodeId); |
| 171 | + if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId)) |
| 172 | + altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId); |
129 | 173 |
|
130 |
| - //initial id |
131 |
| - var idToLoad = id; |
132 |
| - |
133 |
| - //user permission override root |
134 |
| - if (hasUserRoot) |
135 |
| - idToLoad = UserStartNode.ToString(CultureInfo.InvariantCulture); |
136 |
| - |
137 |
| - //tree overrides root |
138 |
| - if (hasTreeRoot) |
| 174 | + //check if a request has been made to render from a specific start node |
| 175 | + if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.Root.ToString(CultureInfo.InvariantCulture)) |
139 | 176 | {
|
140 |
| - //but only if the user is allowed to access this node |
141 |
| - var altId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId); |
142 |
| - |
143 |
| - //so if we dont have a user content root or the user has access |
144 |
| - if (hasUserRoot == false || HasPathAccess(altId, queryStrings)) |
145 |
| - { |
146 |
| - idToLoad = altId; |
147 |
| - } |
| 177 | + id = altStartId; |
148 | 178 | }
|
149 |
| - |
150 |
| - //load whatever root nodes we concluded was the user/tree root |
151 |
| - var nodes = GetTreeNodesInternal(idToLoad, queryStrings); |
152 |
| - |
153 |
| - //only render the recycle bin if we are not in dialog and the start id is still the root |
154 |
| - if (IsDialog(queryStrings) == false && idToLoad == Constants.System.Root.ToInvariantString()) |
| 179 | + |
| 180 | + var nodes = GetTreeNodesInternal(id, queryStrings); |
| 181 | + |
| 182 | + //only render the recycle bin if we are not in dialog and the start id id still the root |
| 183 | + if (IsDialog(queryStrings) == false && id == Constants.System.Root.ToInvariantString()) |
155 | 184 | {
|
156 | 185 | nodes.Add(CreateTreeNode(
|
157 | 186 | RecycleBinId.ToInvariantString(),
|
158 |
| - idToLoad, |
| 187 | + id, |
159 | 188 | queryStrings,
|
160 | 189 | ui.GetText("general", "recycleBin"),
|
161 | 190 | "icon-trash",
|
162 | 191 | RecycleBinSmells,
|
163 | 192 | queryStrings.GetValue<string>("application") + TreeAlias.EnsureStartsWith('/') + "/recyclebin"));
|
| 193 | + |
164 | 194 | }
|
165 | 195 |
|
166 | 196 | return nodes;
|
|
0 commit comments