Skip to content

Commit a5deea9

Browse files
committed
Added new option: save user theme in cookie
1 parent 9ecaee1 commit a5deea9

7 files changed

Lines changed: 130 additions & 23 deletions

File tree

src/Libraries/SmartStore.Core/Domain/Themes/ThemeSettings.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ public ThemeSettings()
3838
/// </summary>
3939
public bool AllowCustomerToSelectTheme { get; set; }
4040

41+
/// <summary>
42+
/// Gets or sets a value indicating whether user's theme choice should be saved in a cookie
43+
/// </summary>
44+
/// <remarks>
45+
/// If <c>false</c>, user's theme choice is associated to the account,
46+
/// which may be undesirable when, for example, multiple users share a guest account.
47+
/// </remarks>
48+
public bool SaveThemeChoiceInCookie { get; set; }
49+
4150
/// <summary>
4251
/// Gets or sets a value indicating whether mobile devices supported
4352
/// </summary>

src/Libraries/SmartStore.Data/Migrations/201503032227054_V22Res.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)
8080
"Spezifikationsattribut zuordnen");
8181
builder.AddOrUpdate("Admin.Catalog.Attributes.SpecificationAttributes.Bundled.ShowNotOnProductPage")
8282
.Value("en", "Don't show on product page");
83+
84+
builder.AddOrUpdate("Admin.Configuration.Themes.Option.SaveThemeChoiceInCookie",
85+
"Save theme choice in cookie",
86+
"Benutzer Theme in Cookie speichern");
87+
builder.AddOrUpdate("Admin.Configuration.Themes.Option.SaveThemeChoiceInCookie.Hint",
88+
"If unchecked, user's theme choice is associated to the account, which may be undesirable when, for example, multiple users share a guest account.",
89+
"Wenn nicht gewählt, wird das Benutzer Theme mit dem Kundenkonto verknüpft, was u.U. unerwünscht sein kann, wenn sich bspw. mehrere User einen Gastzugang teilen.");
90+
91+
/// When <c>false</c>, user's choice will be associated with his account, which may not
92+
/// be desirable in cases where a single guest account is used by many users.
8393
}
8494
}
8595
}

src/Presentation/SmartStore.Web.Framework/Extensions/HttpContextExtensions.cs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,58 @@ public static void RemoveCheckoutState(this HttpContextBase httpContext)
138138
httpContext.Session.SafeRemove(CheckoutState.CheckoutStateSessionKey);
139139
}
140140

141+
internal static string GetUserThemeChoiceFromCookie(this HttpContextBase context)
142+
{
143+
if (context == null)
144+
return null;
145+
146+
var cookie = context.Request.Cookies.Get("sm.UserThemeChoice");
147+
if (cookie != null)
148+
{
149+
return cookie.Value.NullEmpty();
150+
}
151+
152+
return null;
153+
}
154+
155+
internal static void SetUserThemeChoiceInCookie(this HttpContextBase context, string value)
156+
{
157+
if (context == null)
158+
return;
159+
160+
var cookie = context.Request.Cookies.Get("sm.UserThemeChoice");
161+
162+
if (value.HasValue() && cookie == null)
163+
{
164+
cookie = new HttpCookie("sm.UserThemeChoice");
165+
cookie.HttpOnly = true;
166+
cookie.Expires = DateTime.UtcNow.AddYears(1);
167+
}
168+
169+
if (value.HasValue())
170+
{
171+
cookie.Value = value;
172+
context.Request.Cookies.Set(cookie);
173+
}
174+
175+
if (value.IsEmpty() && cookie != null)
176+
{
177+
cookie.Expires = DateTime.UtcNow.AddYears(-10);
178+
}
179+
180+
if (cookie != null)
181+
{
182+
context.Response.SetCookie(cookie);
183+
}
184+
}
185+
141186
internal static HttpCookie GetPreviewModeCookie(this HttpContextBase context, bool createIfMissing)
142187
{
143188
if (context == null)
144189
return null;
145190

146191
var cookie = context.Request.Cookies.Get("sm.PreviewModeOverrides");
147-
192+
148193
if (cookie == null && createIfMissing)
149194
{
150195
cookie = new HttpCookie("sm.PreviewModeOverrides");

src/Presentation/SmartStore.Web.Framework/Themes/ThemeContext.cs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,24 @@ public string WorkingDesktopTheme
6060
return _cachedDesktopThemeName;
6161
}
6262

63-
bool isCustomerSpecific = false;
63+
var customer = _workContext.CurrentCustomer;
64+
bool isUserSpecific = false;
6465
string theme = "";
6566
if (_themeSettings.AllowCustomerToSelectTheme)
6667
{
67-
if (_workContext.CurrentCustomer != null)
68+
if (_themeSettings.SaveThemeChoiceInCookie)
6869
{
69-
theme = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.WorkingDesktopThemeName, _genericAttributeService, _storeContext.CurrentStore.Id);
70-
isCustomerSpecific = theme.HasValue();
70+
theme = _httpContext.GetUserThemeChoiceFromCookie();
7171
}
72+
else
73+
{
74+
if (customer != null)
75+
{
76+
theme = customer.GetAttribute<string>(SystemCustomerAttributeNames.WorkingDesktopThemeName, _genericAttributeService, _storeContext.CurrentStore.Id);
77+
}
78+
}
79+
80+
isUserSpecific = theme.HasValue();
7281
}
7382

7483
// default store theme
@@ -87,10 +96,14 @@ public string WorkingDesktopTheme
8796
throw Error.Application("At least one desktop theme must be in active state, but the theme registry does not contain a valid theme package.");
8897
}
8998
theme = manifest.ThemeName;
90-
if (isCustomerSpecific)
99+
if (isUserSpecific)
91100
{
92-
// the customer chosen theme does not exists (anymore). Invalidate it!
93-
_genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.WorkingDesktopThemeName, string.Empty, _storeContext.CurrentStore.Id);
101+
// the customer chosen theme does not exists (anymore). Invalidate it!
102+
_httpContext.SetUserThemeChoiceInCookie(null);
103+
if (customer != null)
104+
{
105+
_genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.WorkingDesktopThemeName, string.Empty, _storeContext.CurrentStore.Id);
106+
}
94107
}
95108
}
96109

@@ -104,12 +117,14 @@ public string WorkingDesktopTheme
104117
if (!_themeSettings.AllowCustomerToSelectTheme)
105118
return;
106119

107-
if (_workContext.CurrentCustomer == null)
108-
return;
120+
_httpContext.SetUserThemeChoiceInCookie(value);
109121

110-
_genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.WorkingDesktopThemeName, value, _storeContext.CurrentStore.Id);
122+
if (_workContext.CurrentCustomer != null)
123+
{
124+
_genericAttributeService.SaveAttribute(_workContext.CurrentCustomer, SystemCustomerAttributeNames.WorkingDesktopThemeName, value, _storeContext.CurrentStore.Id);
125+
}
111126

112-
//clear cache
127+
// clear cache
113128
this._desktopThemeIsCached = false;
114129
}
115130
}

src/Presentation/SmartStore.Web/Administration/Models/Themes/ThemeListModel.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public ThemeListModel()
3535
[SmartResourceDisplayName("Admin.Configuration.Themes.Option.AllowCustomerToSelectTheme")]
3636
public bool AllowCustomerToSelectTheme { get; set; }
3737

38+
[SmartResourceDisplayName("Admin.Configuration.Themes.Option.SaveThemeChoiceInCookie")]
39+
public bool SaveThemeChoiceInCookie { get; set; }
40+
3841
[SmartResourceDisplayName("Admin.Configuration.Themes.Option.MobileDevicesSupported")]
3942
public bool MobileDevicesSupported { get; set; }
4043

src/Presentation/SmartStore.Web/Administration/Views/Theme/List.cshtml

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//page title
99
ViewBag.Title = T("Admin.Configuration.Themes").Text;
1010
}
11+
1112
@using (Html.BeginForm())
1213
{
1314
<div class="section-header">
@@ -177,21 +178,45 @@
177178

178179
@helper ThemeSettingsTab()
179180
{
180-
181+
<script>
182+
$(function () {
183+
$("#@Html.FieldIdFor(model => model.AllowCustomerToSelectTheme)").on('click', toggleThemeChooser);
184+
toggleThemeChooser();
185+
});
186+
187+
function toggleThemeChooser() {
188+
if ($('#@Html.FieldIdFor(model => model.AllowCustomerToSelectTheme)').is(':checked')) {
189+
$('#pnlSaveThemeChoiceInCookie').show();
190+
}
191+
else {
192+
$('#pnlSaveThemeChoiceInCookie').hide();
193+
}
194+
}
195+
</script>
196+
181197
@Html.HiddenFor(x => x.DefaultDesktopTheme)
182198
@Html.HiddenFor(x => x.DefaultMobileTheme)
183199

184200
@Html.ValidationSummary(false)
185201
<table class="adminContent">
186-
<tr>
187-
<td class="adminTitle">
188-
@Html.SmartLabelFor(model => model.AllowCustomerToSelectTheme)
189-
</td>
190-
<td class="adminData">
191-
@Html.EditorFor(model => model.AllowCustomerToSelectTheme)
192-
@Html.ValidationMessageFor(model => model.AllowCustomerToSelectTheme)
193-
</td>
194-
</tr>
202+
<tr>
203+
<td class="adminTitle">
204+
@Html.SmartLabelFor(model => model.AllowCustomerToSelectTheme)
205+
</td>
206+
<td class="adminData">
207+
@Html.EditorFor(model => model.AllowCustomerToSelectTheme)
208+
@Html.ValidationMessageFor(model => model.AllowCustomerToSelectTheme)
209+
</td>
210+
</tr>
211+
<tr id="pnlSaveThemeChoiceInCookie">
212+
<td class="adminTitle">
213+
@Html.SmartLabelFor(model => model.SaveThemeChoiceInCookie)
214+
</td>
215+
<td class="adminData">
216+
@Html.EditorFor(model => model.SaveThemeChoiceInCookie)
217+
@Html.ValidationMessageFor(model => model.SaveThemeChoiceInCookie)
218+
</td>
219+
</tr>
195220
<tr>
196221
<td class="adminTitle">
197222
@Html.SmartLabelFor(model => model.MobileDevicesSupported)

src/Presentation/SmartStore.Web/Controllers/CommonController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ public ActionResult Footer()
590590
})
591591
.ToList();
592592

593-
var model = new FooterModel()
593+
var model = new FooterModel
594594
{
595595
StoreName = store.Name,
596596
LegalInfo = T("Tax.LegalInfoFooter", taxInfo, shippingInfoLink),

0 commit comments

Comments
 (0)