Skip to content

Commit

Permalink
Look for presets in base theme if current preset specified in current…
Browse files Browse the repository at this point in the history
… theme (#389)

* Look for presets in base theme if current preset specified in current theme

* Fixed bug with additional settings in current theme if preset specified

* Add SettingJsonOverlayMerger

* Fix typo

* Fix naming

* Added tests

* Fixed tests & bug in theme

* Fixed naming

* Fixed backward compatibility

* Refactoring

* Added additional test for case when current is object

Co-authored-by: Eugeny Tatarincev <[email protected]>
  • Loading branch information
asvishnyakov and tatarincev authored Mar 18, 2020
1 parent 5dd323f commit 814ebb9
Show file tree
Hide file tree
Showing 3 changed files with 406 additions and 38 deletions.
92 changes: 92 additions & 0 deletions VirtoCommerce.LiquidThemeEngine/SettingsManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using VirtoCommerce.Storefront.Model.Common.Exceptions;

namespace VirtoCommerce.LiquidThemeEngine
{
public static class SettingsManager
{
public class Settings
{
public Preset CurrentPreset { get; set; }

public IList<Preset> Presets { get; set; } = new List<Preset>();
}

public class Preset
{
public string Name { get; set; }

public JObject Json { get; set; }
}

public static JObject Merge(JObject baseJson, JObject currentJson)
{
if (baseJson == null)
{
throw new ArgumentNullException(nameof(baseJson));
}
if (currentJson == null)
{
throw new ArgumentNullException(nameof(currentJson));
}

var baseSettings = ReadSettings(baseJson);
var currentSettings = ReadSettings(currentJson);
//Change the current preset for base doc according to head preset value if it specified
if (!string.IsNullOrEmpty(currentSettings.CurrentPreset.Name))
{
baseSettings.CurrentPreset = baseSettings.Presets.FirstOrDefault(x => x.Name == currentSettings.CurrentPreset.Name);
}
var result = baseSettings.CurrentPreset?.Json ?? new JObject();
result.Merge(currentSettings.CurrentPreset.Json, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge });
return result;
}

public static Settings ReadSettings(JObject json)
{
var result = new Settings
{
CurrentPreset = new Preset
{
Json = json
}
};

if (json.GetValue("presets") is JObject presetsJson)
{
var allPresetsJsonProperties = presetsJson.Children().Cast<JProperty>().ToList();
foreach (var presetJsonProperty in allPresetsJsonProperties)
{
var preset = new Preset
{
Name = presetJsonProperty.Name,
Json = presetJsonProperty.Value as JObject
};
result.Presets.Add(preset);
}
}

var currentPresetJsonToken = json.GetValue("current");
if (currentPresetJsonToken is JValue currentPresetJsonValue)
{
var presetName = currentPresetJsonValue.Value.ToString();
var currentPresetJson = result.Presets.FirstOrDefault(x => x.Name == presetName)?.Json;
if (currentPresetJson == null && result.Presets.Any())
{
throw new StorefrontException($"Setting preset with name '{presetName}' not found");
}
result.CurrentPreset.Name = presetName;
result.CurrentPreset.Json = currentPresetJson ?? json;
}
if (currentPresetJsonToken is JObject)
{
result.CurrentPreset.Json = currentPresetJsonToken as JObject;
}

return result;
}
}
}
45 changes: 7 additions & 38 deletions VirtoCommerce.LiquidThemeEngine/ShopifyLiquidThemeEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,20 +358,18 @@ public IDictionary<string, object> GetSettings(string defaultValue = null)

JObject result;
var baseThemeSettings = new JObject();
var currentThemeSettings = result = GetCurrentSettingsPreset(InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath));
var currentThemeSettings = result = InnerGetAllSettings(_themeBlobProvider, CurrentThemeSettingPath);

//Try to load settings from base theme path and merge them with resources for local theme
if ((_options.MergeBaseSettings || currentThemeSettings == null) && !string.IsNullOrEmpty(BaseThemeSettingPath))
{
cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeSettingPath) }));
result = baseThemeSettings = GetCurrentSettingsPreset(InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath));
baseThemeSettings = InnerGetAllSettings(_themeBlobProvider, BaseThemeSettingPath);
}

if (_options.MergeBaseSettings)
{
result = baseThemeSettings;
result.Merge(currentThemeSettings ?? new JObject(), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge });
}
result = _options.MergeBaseSettings
? SettingsManager.Merge(baseThemeSettings, currentThemeSettings ?? new JObject())
: SettingsManager.ReadSettings(currentThemeSettings ?? new JObject()).CurrentPreset.Json;

return result.ToObject<Dictionary<string, object>>().ToDictionary(x => x.Key, x => x.Value).WithDefaultValue(defaultValue);
});
Expand All @@ -393,7 +391,7 @@ public JObject ReadLocalization()
if (BaseThemeLocalePath != null)
{
cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeLocalePath + "/*") }));
result = InnerReadLocalization(_themeBlobProvider, BaseThemeLocalePath, WorkContext.CurrentLanguage);
result = InnerReadLocalization(_themeBlobProvider, BaseThemeLocalePath, WorkContext.CurrentLanguage) ?? new JObject();
}
result.Merge(InnerReadLocalization(_themeBlobProvider, CurrentThemeLocalePath, WorkContext.CurrentLanguage) ?? new JObject(), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge });
return result;
Expand Down Expand Up @@ -476,36 +474,7 @@ private static JObject InnerGetAllSettings(IContentBlobProvider themeBlobProvide
return result;
}

/// <summary>
/// Get actual preset from config
/// </summary>
/// <returns></returns>
private static JObject GetCurrentSettingsPreset(JObject allSettings)
{
var result = allSettings;
var currentPreset = allSettings.GetValue("current");
if (currentPreset is JValue currentPresetValue)
{
var currentPresetName = currentPresetValue.Value.ToString();
if (!(allSettings.GetValue("presets") is JObject presets) || !presets.Children().Any())
{
throw new StorefrontException("Setting presets not defined");
}

IList<JProperty> allPresets = presets.Children().Cast<JProperty>().ToList();
result = allPresets.FirstOrDefault(p => p.Name == currentPresetName)?.Value as JObject;
if (result == null)
{
throw new StorefrontException($"Setting preset with name '{currentPresetName}' not found");
}
}
if (currentPreset is JObject preset)
{
result = preset;
}

return result;
}


private string ReadTemplateByPath(string templatePath)
{
Expand Down
Loading

0 comments on commit 814ebb9

Please sign in to comment.