Skip to content

Commit d0938ba

Browse files
committed
Refactored PlaceHolder processing to use Stack approach instead of recursion
1 parent fb2f772 commit d0938ba

2 files changed

Lines changed: 91 additions & 24 deletions

File tree

src/Sitecore.AspNetCore.SDK.Pages/Request/Handlers/GraphQL/GraphQLEditingServiceHandler.cs

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace Sitecore.AspNetCore.SDK.Pages.Request.Handlers.GraphQL;
2222
/// <param name="logger">The <see cref="ILogger"/> to use for logging.</param>
2323
/// <param name="clientFactory">The GraphQlClientFactory used to generate instances of the GraphQl client.</param>
2424
/// <param name="serializer">The serializer to handle response data.</param>
25-
public class GraphQLEditingServiceHandler(IGraphQLClientFactory clientFactory,
25+
public partial class GraphQLEditingServiceHandler(IGraphQLClientFactory clientFactory,
2626
ISitecoreLayoutSerializer serializer,
2727
ILogger<GraphQLEditingServiceHandler> logger)
2828
: ILayoutRequestHandler
@@ -93,43 +93,77 @@ private static void GenerateMetaDataChromes(SitecoreLayoutResponseContent? conte
9393

9494
private static Placeholder ProcessPlaceholder(string name, string id, Placeholder placeholderFeatures)
9595
{
96-
Placeholder updatedPlaceholders = [];
96+
Placeholder result = new();
9797

98-
AddPlaceholderOpeningChrome(name, id, updatedPlaceholders);
98+
// Create a separate class outside of this method for the work item
99+
// to avoid nested class compilation issues
100+
var workStack = new Stack<PlaceholderWorkItem>();
101+
workStack.Push(new PlaceholderWorkItem(name, id, placeholderFeatures, result));
99102

100-
foreach (var feature in placeholderFeatures)
103+
while (workStack.Count > 0)
101104
{
102-
if (feature is Component component)
103-
{
104-
AddRenderingOpeningChrome(updatedPlaceholders, component);
105+
var current = workStack.Pop();
106+
var output = current.Output;
107+
108+
// Add opening chrome for placeholder
109+
AddPlaceholderOpeningChrome(current.Name, current.Id, output);
105110

106-
var updatedFields = new Dictionary<string, IFieldReader>();
107-
foreach (var field in component.Fields)
111+
// Process all features in this placeholder
112+
foreach (var feature in current.Features)
113+
{
114+
if (feature is Component component)
108115
{
109-
ProcessField(updatedFields, field);
110-
}
116+
// Add opening chrome
117+
AddRenderingOpeningChrome(output, component);
111118

112-
component.Fields = updatedFields;
119+
// Process fields
120+
Dictionary<string, IFieldReader> updatedFields = new();
121+
foreach (var field in component.Fields)
122+
{
123+
ProcessField(updatedFields, field);
124+
}
125+
component.Fields = updatedFields;
113126

114-
updatedPlaceholders.Add(component);
127+
// Add the component to the output
128+
output.Add(component);
115129

116-
foreach (var componentPlaceholder in component.Placeholders)
117-
{
130+
// Process component placeholders before adding closing chrome
131+
if (component.Placeholders.Count > 0)
118132
{
119-
string componentPlaceholderName = componentPlaceholder.Key;
120-
Placeholder componentPlaceholderFeatures = componentPlaceholder.Value;
121-
122-
component.Placeholders[componentPlaceholderName] = ProcessPlaceholder("container-{*}", component.Id, componentPlaceholderFeatures);
133+
// For each placeholder in the component, add it to the work stack
134+
foreach (var placeholder in component.Placeholders.ToList())
135+
{
136+
string placeholderKey = placeholder.Key;
137+
Placeholder placeholderValue = placeholder.Value;
138+
139+
// Create a new placeholder to hold the processed content
140+
Placeholder processedPlaceholder = new();
141+
142+
// Add a work item to process this placeholder
143+
workStack.Push(new PlaceholderWorkItem(
144+
"container-{*}",
145+
component.Id,
146+
placeholderValue,
147+
processedPlaceholder,
148+
component,
149+
placeholderKey
150+
));
151+
152+
// Store the processed placeholder for later assignment
153+
component.Placeholders[placeholderKey] = processedPlaceholder;
154+
}
123155
}
124-
}
125156

126-
AddRenderingClosingChrome(updatedPlaceholders);
157+
// Add closing chrome for the component
158+
AddRenderingClosingChrome(output);
159+
}
127160
}
128-
}
129161

130-
AddPlaceholderClosingChrome(updatedPlaceholders);
162+
// Add closing chrome for placeholder
163+
AddPlaceholderClosingChrome(output);
164+
}
131165

132-
return updatedPlaceholders;
166+
return result;
133167
}
134168

135169
private static void AddRenderingClosingChrome(Placeholder updatedPlaceholders)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Sitecore.AspNetCore.SDK.LayoutService.Client.Response.Model;
2+
3+
namespace Sitecore.AspNetCore.SDK.Pages.Request.Handlers.GraphQL;
4+
5+
public partial class GraphQLEditingServiceHandler
6+
{
7+
// Define the work item class outside of the method to avoid nested class issues
8+
private class PlaceholderWorkItem
9+
{
10+
public string Name { get; }
11+
public string Id { get; }
12+
public Placeholder Features { get; }
13+
public Placeholder Output { get; }
14+
public Component ParentComponent { get; }
15+
public string PlaceholderKey { get; }
16+
17+
public PlaceholderWorkItem(
18+
string name,
19+
string id,
20+
Placeholder features,
21+
Placeholder output,
22+
Component parentComponent = null,
23+
string placeholderKey = null)
24+
{
25+
Name = name;
26+
Id = id;
27+
Features = features;
28+
Output = output;
29+
ParentComponent = parentComponent;
30+
PlaceholderKey = placeholderKey;
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)