mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-03 03:58:13 +08:00
Merge
--HG-- branch : 1.x
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
eb12bf266fcd8334b7a20d7553dd28f9c80dfa07 src/Orchard.Web/Modules/Orchard.Forms
|
eb12bf266fcd8334b7a20d7553dd28f9c80dfa07 src/Orchard.Web/Modules/Orchard.Forms
|
||||||
8a370b966ac7ccbb6564af4b748084c2e68438d3 src/Orchard.Web/Modules/Orchard.Projections
|
6668e827c75141ac2f49664a1f6461b8aa7ee618 src/Orchard.Web/Modules/Orchard.Projections
|
||||||
7e6e3d2e72d94c3f78e8aecc0aa87ede108226bd src/Orchard.Web/Modules/Orchard.Rules
|
7e6e3d2e72d94c3f78e8aecc0aa87ede108226bd src/Orchard.Web/Modules/Orchard.Rules
|
||||||
c6098ad6c3fdb614901e8946d8e298e3c50f3ea1 src/Orchard.Web/Modules/Orchard.TaskLease
|
c6098ad6c3fdb614901e8946d8e298e3c50f3ea1 src/Orchard.Web/Modules/Orchard.TaskLease
|
||||||
4c4fd36df9d1337c0b6801960d02221debcf4388 src/Orchard.Web/Modules/Orchard.Tokens
|
4c4fd36df9d1337c0b6801960d02221debcf4388 src/Orchard.Web/Modules/Orchard.Tokens
|
||||||
|
|||||||
@@ -63,10 +63,6 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Autofac.Integration.Web.Mvc, Version=2.1.13.813, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.Mvc.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Castle.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
<Reference Include="Castle.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
|
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
|
||||||
|
|||||||
@@ -63,10 +63,6 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Autofac.Integration.Web.Mvc, Version=2.1.13.813, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.Mvc.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Castle.Core, Version=1.2.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
<Reference Include="Castle.Core, Version=1.2.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
|
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
|
||||||
@@ -278,6 +274,7 @@
|
|||||||
<Compile Include="Stubs\StubVirtualPathMonitor.cs" />
|
<Compile Include="Stubs\StubVirtualPathMonitor.cs" />
|
||||||
<Compile Include="Stubs\StubCacheManager.cs" />
|
<Compile Include="Stubs\StubCacheManager.cs" />
|
||||||
<Compile Include="Stubs\StubWebSiteFolder.cs" />
|
<Compile Include="Stubs\StubWebSiteFolder.cs" />
|
||||||
|
<Compile Include="Time\TimeZoneSelectorTests.cs" />
|
||||||
<Compile Include="UI\Resources\ResourceManagerTests.cs" />
|
<Compile Include="UI\Resources\ResourceManagerTests.cs" />
|
||||||
<Compile Include="UI\ShapeTests.cs" />
|
<Compile Include="UI\ShapeTests.cs" />
|
||||||
<Compile Include="Utility\ContainerExtensions.cs" />
|
<Compile Include="Utility\ContainerExtensions.cs" />
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ namespace Orchard.Tests.Stubs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string BaseUrl { get; set;}
|
public string BaseUrl { get; set;}
|
||||||
|
|
||||||
|
public string SiteTimeZone { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StubUser : IUser {
|
public class StubUser : IUser {
|
||||||
|
|||||||
85
src/Orchard.Tests/Time/TimeZoneSelectorTests.cs
Normal file
85
src/Orchard.Tests/Time/TimeZoneSelectorTests.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Web;
|
||||||
|
using Autofac;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Orchard.Tests.Stubs;
|
||||||
|
using Orchard.Time;
|
||||||
|
|
||||||
|
namespace Orchard.Tests.Time {
|
||||||
|
[TestFixture]
|
||||||
|
public class TimeZoneProviderTests {
|
||||||
|
private IContainer _container;
|
||||||
|
private IWorkContextStateProvider _workContextStateProvider;
|
||||||
|
private TestTimeZoneSelector _timeZoneSelector;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init() {
|
||||||
|
var builder = new ContainerBuilder();
|
||||||
|
builder.RegisterInstance(_timeZoneSelector = new TestTimeZoneSelector()).As<ITimeZoneSelector>();
|
||||||
|
builder.RegisterType<CurrentTimeZoneWorkContext>().As<IWorkContextStateProvider>();
|
||||||
|
builder.RegisterType<FallbackTimeZoneSelector>().As<ITimeZoneSelector>();
|
||||||
|
builder.RegisterType<SiteTimeZoneSelector>().As<ITimeZoneSelector>();
|
||||||
|
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||||
|
|
||||||
|
_container = builder.Build();
|
||||||
|
_workContextStateProvider = _container.Resolve<IWorkContextStateProvider>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldProvideCurrentTimeZoneOnly() {
|
||||||
|
_timeZoneSelector.TimeZone = null;
|
||||||
|
var timeZone = _workContextStateProvider.Get<TimeZoneInfo>("Foo");
|
||||||
|
|
||||||
|
Assert.That(timeZone, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DefaultTimeZoneIsLocal() {
|
||||||
|
_timeZoneSelector.Priority = -200;
|
||||||
|
var timeZone = _workContextStateProvider.Get<TimeZoneInfo>("CurrentTimeZone");
|
||||||
|
|
||||||
|
Assert.That(timeZone(new StubWorkContext()), Is.EqualTo(TimeZoneInfo.Local));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TimeZoneProviderReturnsTimeZoneFromSelector() {
|
||||||
|
_timeZoneSelector.Priority = 999;
|
||||||
|
_timeZoneSelector.TimeZone = TimeZoneInfo.Utc;
|
||||||
|
var timeZone = _workContextStateProvider.Get<TimeZoneInfo>("CurrentTimeZone");
|
||||||
|
|
||||||
|
Assert.That(timeZone(new StubWorkContext()), Is.EqualTo(TimeZoneInfo.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestTimeZoneSelector : ITimeZoneSelector {
|
||||||
|
public TimeZoneInfo TimeZone { get; set; }
|
||||||
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
|
||||||
|
return new TimeZoneSelectorResult {
|
||||||
|
Priority = Priority,
|
||||||
|
TimeZone= TimeZone
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StubWorkContext : WorkContext {
|
||||||
|
public override T Resolve<T>() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool TryResolve<T>(out T service) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override T GetState<T>(string name) {
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetState<T>(string name, T value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -23,12 +23,12 @@ namespace Orchard.Core.Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Shape]
|
[Shape]
|
||||||
public IHtmlString PublishedState(HtmlHelper html, DateTime createdDateTimeUtc, DateTime? publisheddateTimeUtc) {
|
public IHtmlString PublishedState(dynamic Display, DateTime createdDateTimeUtc, DateTime? publisheddateTimeUtc) {
|
||||||
if (!publisheddateTimeUtc.HasValue) {
|
if (!publisheddateTimeUtc.HasValue) {
|
||||||
return T("Draft");
|
return T("Draft");
|
||||||
}
|
}
|
||||||
|
|
||||||
return html.DateTime(createdDateTimeUtc);
|
return Display.DateTime(DateTimeUtc: createdDateTimeUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Shape]
|
[Shape]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Net;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.ContentManagement.Drivers;
|
using Orchard.ContentManagement.Drivers;
|
||||||
@@ -44,7 +45,8 @@ namespace Orchard.Core.Settings.Drivers {
|
|||||||
|
|
||||||
var model = new SiteSettingsPartViewModel {
|
var model = new SiteSettingsPartViewModel {
|
||||||
Site = site,
|
Site = site,
|
||||||
SiteCultures = _cultureManager.ListCultures()
|
SiteCultures = _cultureManager.ListCultures(),
|
||||||
|
TimeZones = TimeZoneInfo.GetSystemTimeZones()
|
||||||
};
|
};
|
||||||
|
|
||||||
return ContentShape("Parts_Settings_SiteSettingsPart",
|
return ContentShape("Parts_Settings_SiteSettingsPart",
|
||||||
@@ -55,7 +57,8 @@ namespace Orchard.Core.Settings.Drivers {
|
|||||||
var site = _siteService.GetSiteSettings().As<SiteSettingsPart>();
|
var site = _siteService.GetSiteSettings().As<SiteSettingsPart>();
|
||||||
var model = new SiteSettingsPartViewModel {
|
var model = new SiteSettingsPartViewModel {
|
||||||
Site = site,
|
Site = site,
|
||||||
SiteCultures = _cultureManager.ListCultures()
|
SiteCultures = _cultureManager.ListCultures(),
|
||||||
|
TimeZones = TimeZoneInfo.GetSystemTimeZones()
|
||||||
};
|
};
|
||||||
|
|
||||||
var previousBaseUrl = model.Site.BaseUrl;
|
var previousBaseUrl = model.Site.BaseUrl;
|
||||||
|
|||||||
@@ -91,9 +91,16 @@ namespace Orchard.Core.Settings {
|
|||||||
.Column<string>("SiteCulture")
|
.Column<string>("SiteCulture")
|
||||||
.Column<string>("ResourceDebugMode", c => c.WithDefault("FromAppSetting"))
|
.Column<string>("ResourceDebugMode", c => c.WithDefault("FromAppSetting"))
|
||||||
.Column<int>("PageSize")
|
.Column<int>("PageSize")
|
||||||
|
.Column<string>("SiteTimeZone")
|
||||||
);
|
);
|
||||||
|
|
||||||
return 1;
|
SchemaBuilder.CreateTable("SiteSettings2PartRecord",
|
||||||
|
table => table
|
||||||
|
.ContentPartRecord()
|
||||||
|
.Column<string>("BaseUrl", c => c.Unlimited())
|
||||||
|
);
|
||||||
|
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int UpdateFrom1() {
|
public int UpdateFrom1() {
|
||||||
@@ -105,5 +112,14 @@ namespace Orchard.Core.Settings {
|
|||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int UpdateFrom2() {
|
||||||
|
SchemaBuilder.AlterTable("SiteSettingsPartRecord",
|
||||||
|
table => table
|
||||||
|
.AddColumn<string>("SiteTimeZone")
|
||||||
|
);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.Data.Conventions;
|
using Orchard.Data.Conventions;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
@@ -45,6 +46,11 @@ namespace Orchard.Core.Settings.Models {
|
|||||||
set { Record.PageSize = value; }
|
set { Record.PageSize = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string SiteTimeZone {
|
||||||
|
get { return Record.SiteTimeZone; }
|
||||||
|
set { Record.SiteTimeZone = value; }
|
||||||
|
}
|
||||||
|
|
||||||
[StringLengthMax]
|
[StringLengthMax]
|
||||||
public string BaseUrl {
|
public string BaseUrl {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Orchard.ContentManagement.Records;
|
using System;
|
||||||
|
using Orchard.ContentManagement.Records;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
|
|
||||||
namespace Orchard.Core.Settings.Models {
|
namespace Orchard.Core.Settings.Models {
|
||||||
@@ -24,5 +25,7 @@ namespace Orchard.Core.Settings.Models {
|
|||||||
public virtual ResourceDebugMode ResourceDebugMode { get; set; }
|
public virtual ResourceDebugMode ResourceDebugMode { get; set; }
|
||||||
|
|
||||||
public virtual int PageSize { get; set; }
|
public virtual int PageSize { get; set; }
|
||||||
|
|
||||||
|
public virtual string SiteTimeZone { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,7 @@ namespace Orchard.Core.Settings.Services {
|
|||||||
item.Record.SiteSalt = Guid.NewGuid().ToString("N");
|
item.Record.SiteSalt = Guid.NewGuid().ToString("N");
|
||||||
item.Record.SiteName = "My Orchard Project Application";
|
item.Record.SiteName = "My Orchard Project Application";
|
||||||
item.Record.PageTitleSeparator = " - ";
|
item.Record.PageTitleSeparator = " - ";
|
||||||
|
item.Record.SiteTimeZone = TimeZoneInfo.Local.Id;
|
||||||
}).ContentItem;
|
}).ContentItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using Orchard.Core.Settings.Models;
|
using Orchard.Core.Settings.Models;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
@@ -7,6 +8,7 @@ namespace Orchard.Core.Settings.ViewModels {
|
|||||||
public class SiteSettingsPartViewModel {
|
public class SiteSettingsPartViewModel {
|
||||||
public SiteSettingsPart Site { get; set; }
|
public SiteSettingsPart Site { get; set; }
|
||||||
public IEnumerable<string> SiteCultures { get; set; }
|
public IEnumerable<string> SiteCultures { get; set; }
|
||||||
|
public IEnumerable<TimeZoneInfo> TimeZones { get; set; }
|
||||||
|
|
||||||
[HiddenInput(DisplayValue = false)]
|
[HiddenInput(DisplayValue = false)]
|
||||||
public int Id {
|
public int Id {
|
||||||
@@ -47,5 +49,10 @@ namespace Orchard.Core.Settings.ViewModels {
|
|||||||
get { return Site.BaseUrl; }
|
get { return Site.BaseUrl; }
|
||||||
set { Site.BaseUrl = value; }
|
set { Site.BaseUrl = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string TimeZone {
|
||||||
|
get { return Site.SiteTimeZone; }
|
||||||
|
set { Site.SiteTimeZone = value; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,12 @@
|
|||||||
@Html.ValidationMessage("SiteCulture", "*")
|
@Html.ValidationMessage("SiteCulture", "*")
|
||||||
<p>@Html.ActionLink(T("Add or remove supported cultures for the site.").ToString(), "Culture")</p>
|
<p>@Html.ActionLink(T("Add or remove supported cultures for the site.").ToString(), "Culture")</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="TimeZone">@T("Default Time Zone")</label>
|
||||||
|
@Html.DropDownList("TimeZone", new[] { new SelectListItem { Text = T("Local to server").Text, Value = "" } }.Union(new SelectList(Model.TimeZones, "Id", "", Model.TimeZone)))
|
||||||
|
@Html.ValidationMessage("TimeZone", "*")
|
||||||
|
<span class="hint">@T("Determines the default time zone which will should be used to display date and times.")</span>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="PageTitleSeparator">@T("Page title separator")</label>
|
<label for="PageTitleSeparator">@T("Page title separator")</label>
|
||||||
@Html.EditorFor(x => x.PageTitleSeparator)
|
@Html.EditorFor(x => x.PageTitleSeparator)
|
||||||
|
|||||||
@@ -7,22 +7,27 @@ using Orchard.Mvc.Html;
|
|||||||
using Orchard.Services;
|
using Orchard.Services;
|
||||||
|
|
||||||
namespace Orchard.Core.Shapes {
|
namespace Orchard.Core.Shapes {
|
||||||
public class DateTimeShapes : ISingletonDependency {
|
public class DateTimeShapes : IDependency {
|
||||||
private readonly IClock _clock;
|
private readonly IClock _clock;
|
||||||
|
private readonly IWorkContextAccessor _workContextAccessor;
|
||||||
|
|
||||||
public DateTimeShapes(IClock clock) {
|
public DateTimeShapes(
|
||||||
|
IClock clock,
|
||||||
|
IWorkContextAccessor workContextAccessor
|
||||||
|
) {
|
||||||
_clock = clock;
|
_clock = clock;
|
||||||
|
_workContextAccessor = workContextAccessor;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
[Shape]
|
[Shape]
|
||||||
public IHtmlString DateTimeRelative(HtmlHelper Html, DateTime dateTimeUtc) {
|
public IHtmlString DateTimeRelative(dynamic Display, DateTime dateTimeUtc) {
|
||||||
var time = _clock.UtcNow - dateTimeUtc;
|
var time = _clock.UtcNow - dateTimeUtc;
|
||||||
|
|
||||||
if (time.TotalDays > 7)
|
if (time.TotalDays > 7)
|
||||||
return Html.DateTime(dateTimeUtc.ToLocalTime(), T("'on' MMM d yyyy 'at' h:mm tt"));
|
return Display.DateTime(DateTimeUtc: dateTimeUtc, CustomFormat: T("'on' MMM d yyyy 'at' h:mm tt"));
|
||||||
if (time.TotalHours > 24)
|
if (time.TotalHours > 24)
|
||||||
return T.Plural("1 day ago", "{0} days ago", time.Days);
|
return T.Plural("1 day ago", "{0} days ago", time.Days);
|
||||||
if (time.TotalMinutes > 60)
|
if (time.TotalMinutes > 60)
|
||||||
@@ -34,5 +39,30 @@ namespace Orchard.Core.Shapes {
|
|||||||
|
|
||||||
return T("a moment ago");
|
return T("a moment ago");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Shape]
|
||||||
|
public IHtmlString DateTime(DateTime DateTimeUtc, LocalizedString CustomFormat) {
|
||||||
|
//using a LocalizedString forces the caller to use a localizable format
|
||||||
|
|
||||||
|
if (CustomFormat == null || String.IsNullOrWhiteSpace(CustomFormat.Text)) {
|
||||||
|
return DateTime(DateTimeUtc, T("MMM d yyyy h:mm tt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MvcHtmlString(ConvertToDisplayTime(DateTimeUtc).ToString(CustomFormat.Text));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a Coordinated Universal Time (UTC) to the time in the current time zone.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateTimeUtc">The Coordinated Universal Time (UTC).</param>
|
||||||
|
/// <returns>The date and time in the selected time zone. Its System.DateTime.Kind property is System.DateTimeKind.Utc if the current zone is System.TimeZoneInfo.Utc; otherwise, its System.DateTime.Kind property is System.DateTimeKind.Unspecified.</returns>
|
||||||
|
private DateTime ConvertToDisplayTime(DateTime dateTimeUtc) {
|
||||||
|
|
||||||
|
// get the time zone for the current request
|
||||||
|
var timeZone = _workContextAccessor.GetContext().CurrentTimeZone;
|
||||||
|
|
||||||
|
return TimeZoneInfo.ConvertTimeFromUtc(dateTimeUtc, timeZone);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<ul class="pageStatus">
|
<ul class="pageStatus">
|
||||||
<li>
|
<li>
|
||||||
<img class="icon" src="@Href("~/Modules/Orchard.ArchiveLater/Content/Admin/images/scheduled.gif")" alt="@T("Scheduled")" title="@T("The page is scheduled for archiving")" />@T("Unpublish on")
|
<img class="icon" src="@Href("~/Modules/Orchard.ArchiveLater/Content/Admin/images/scheduled.gif")" alt="@T("Scheduled")" title="@T("The page is scheduled for archiving")" />@T("Unpublish on")
|
||||||
@Html.DateTime((DateTime)Model.ScheduledArchiveUtc.ToLocalTime(), T("M/d/yyyy h:mm tt"))
|
@Display.DateTime(DateTimeUtc: (DateTime)Model.ScheduledArchiveUtc.ToLocalTime(), CustomFormat: T("M/d/yyyy h:mm tt"))
|
||||||
|
|
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
@text
|
@text
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td>@Html.DateTime(commentEntry.Comment.CommentDateUtc.GetValueOrDefault())</td>
|
<td>@Display.DateTime(DateTimeUtc: commentEntry.Comment.CommentDateUtc.GetValueOrDefault())</td>
|
||||||
<td>
|
<td>
|
||||||
<ul class="actions">
|
<ul class="actions">
|
||||||
<li class="construct">
|
<li class="construct">
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@* would ideally have permalinks for individual comments *@
|
@* would ideally have permalinks for individual comments *@
|
||||||
<p><a href="@Url.ItemDisplayUrl(commentEntry.CommentedOn)#comments"><time>@Html.DateTime(commentEntry.Comment.CommentDateUtc.GetValueOrDefault())</time></a></p>
|
<p><a href="@Url.ItemDisplayUrl(commentEntry.CommentedOn)#comments"><time>@Display.DateTime(DateTimeUtc: commentEntry.Comment.CommentDateUtc.GetValueOrDefault())</time></a></p>
|
||||||
@if (commentEntry.Comment.CommentText != null) {
|
@if (commentEntry.Comment.CommentText != null) {
|
||||||
var ellipsized = Html.Ellipsize(commentEntry.Comment.CommentText, 500);
|
var ellipsized = Html.Ellipsize(commentEntry.Comment.CommentText, 500);
|
||||||
var paragraphed = new HtmlString(ellipsized.ToHtmlString().Replace("\r\n", "</p><p>"));
|
var paragraphed = new HtmlString(ellipsized.ToHtmlString().Replace("\r\n", "</p><p>"));
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<fieldset class="manage-field">
|
<fieldset class="manage-field">
|
||||||
<h3>@Model.DisplayName <span>(@Model.FieldDefinition.Name)</span></h3>
|
<h3>@Model.DisplayName <span>(@Model.FieldDefinition.Name)</span></h3>
|
||||||
<div class="manage">
|
<div class="manage">
|
||||||
@Html.ActionLink(T("Edit").Text, "EditField", new { area = "Orchard.ContentTypes", id = Model.Part.Name, Model.Name }, new { itemprop = "RemoveUrl UnsafeUrl" }) |
|
@Html.ActionLink(T("Edit").Text, "EditField", new { area = "Orchard.ContentTypes", id = Model.Part.Name, Model.Name }) |
|
||||||
@Html.ActionLink(T("Remove").Text, "RemoveFieldFrom", new { area = "Orchard.ContentTypes", id = Model.Part.Name, Model.Name }, new { itemprop = "RemoveUrl UnsafeUrl" }) @* <- some experimentation *@
|
@Html.ActionLink(T("Remove").Text, "RemoveFieldFrom", new { area = "Orchard.ContentTypes", id = Model.Part.Name, Model.Name }, new { itemprop = "RemoveUrl UnsafeUrl" })
|
||||||
</div>
|
</div>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
@{Html.RenderTemplates(Model.Templates);}
|
@{Html.RenderTemplates(Model.Templates);}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace Orchard.Modules.Services {
|
|||||||
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
/// <param name="force">Boolean parameter indicating if the feature should enable it's dependencies if required or fail otherwise.</param>
|
||||||
public void EnableFeatures(IEnumerable<string> featureIds, bool force) {
|
public void EnableFeatures(IEnumerable<string> featureIds, bool force) {
|
||||||
foreach (string featureId in _featureManager.EnableFeatures(featureIds, force)) {
|
foreach (string featureId in _featureManager.EnableFeatures(featureIds, force)) {
|
||||||
var featureName = _featureManager.GetAvailableFeatures().Where(f => f.Id == featureId).First().Name;
|
var featureName = _featureManager.GetAvailableFeatures().First(f => f.Id.Equals(featureId, StringComparison.OrdinalIgnoreCase)).Name;
|
||||||
Services.Notifier.Information(T("{0} was enabled", featureName));
|
Services.Notifier.Information(T("{0} was enabled", featureName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,16 +49,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dependencies = (from d in feature.Descriptor.Dependencies
|
var dependencies = (from d in feature.Descriptor.Dependencies
|
||||||
select (from f in Model.Features where f.Descriptor.Id == d select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name);
|
select (from f in Model.Features where f.Descriptor.Id.Equals(d, StringComparison.OrdinalIgnoreCase) select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name);
|
||||||
var missingDependencies = feature.Descriptor.Dependencies
|
var missingDependencies = feature.Descriptor.Dependencies
|
||||||
.Where(d => !Model.Features.Any(f => f.Descriptor.Id == d));
|
.Where(d => !Model.Features.Any(f => f.Descriptor.Id.Equals(d, StringComparison.OrdinalIgnoreCase)));
|
||||||
showDisable = categoryName.ToString() != "Core";
|
showDisable = categoryName.ToString() != "Core";
|
||||||
showEnable = missingDependencies.Count() == 0 && feature.Descriptor.Id != "Orchard.Setup";
|
showEnable = !missingDependencies.Any() && feature.Descriptor.Id != "Orchard.Setup";
|
||||||
<li class="@featureClassName" id="@featureId" title="@T("{0} is {1}", Html.AttributeEncode(featureName), featureState)">
|
<li class="@featureClassName" id="@featureId" title="@T("{0} is {1}", Html.AttributeEncode(featureName), featureState)">
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
<div class="properties">
|
<div class="properties">
|
||||||
<h3>@featureName</h3>
|
<h3>@featureName</h3>
|
||||||
<p class="description">@feature.Descriptor.Description</p>@if (feature.Descriptor.Dependencies != null && feature.Descriptor.Dependencies.Any()) {
|
<p class="description">@feature.Descriptor.Description</p>
|
||||||
|
@if (feature.Descriptor.Dependencies != null && feature.Descriptor.Dependencies.Any()) {
|
||||||
<div class="dependencies">
|
<div class="dependencies">
|
||||||
<h4>@T("Depends on:")</h4>
|
<h4>@T("Depends on:")</h4>
|
||||||
@Html.UnorderedList(dependencies,
|
@Html.UnorderedList(dependencies,
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Orchard.MultiTenancy.Services {
|
|||||||
|
|
||||||
ExtensionDescriptor theme = descriptor;
|
ExtensionDescriptor theme = descriptor;
|
||||||
|
|
||||||
if (!theme.Tags.Contains("hidden")) {
|
if (theme.Tags == null || !theme.Tags.Contains("hidden")) {
|
||||||
themes.Add(theme);
|
themes.Add(theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Hosting;
|
using System.Web.Hosting;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
using System.Xml.Linq;
|
||||||
using NuGet;
|
using NuGet;
|
||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
@@ -227,8 +228,17 @@ namespace Orchard.Packaging.Controllers {
|
|||||||
.Where(feature => feature.Enable)
|
.Where(feature => feature.Enable)
|
||||||
.Select(feature => feature.FeatureDescriptor.Id);
|
.Select(feature => feature.FeatureDescriptor.Id);
|
||||||
|
|
||||||
// Enable the features and its dependencies
|
// Enable the features and its dependencies using recipes, so that they are run after the module's recipes
|
||||||
_moduleService.EnableFeatures(featureIds, true);
|
|
||||||
|
var recipe = new Recipe {
|
||||||
|
RecipeSteps = featureIds.Select(
|
||||||
|
x => new RecipeStep {
|
||||||
|
Name = "Feature",
|
||||||
|
Step = new XElement("Feature", new XAttribute("enable", x))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
_recipeManager.Execute(recipe);
|
||||||
}
|
}
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
Services.Notifier.Error(T("Post installation steps failed with error: {0}", exception.Message));
|
Services.Notifier.Error(T("Post installation steps failed with error: {0}", exception.Message));
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<img class="icon" src="@Href("~/Modules/Orchard.PublishLater/Content/Admin/images/scheduled.gif")" alt="@T("Scheduled")" title="@T("The page is scheduled for publishing")" /><text> @T("Scheduled") </text>
|
<img class="icon" src="@Href("~/Modules/Orchard.PublishLater/Content/Admin/images/scheduled.gif")" alt="@T("Scheduled")" title="@T("The page is scheduled for publishing")" /><text> @T("Scheduled") </text>
|
||||||
@Html.DateTime(((DateTime?)Model.ScheduledPublishUtc).Value.ToLocalTime(), T("M/d/yyyy h:mm tt"))
|
@Display.DateTime(((DateTime?)Model.ScheduledPublishUtc).Value.ToLocalTime(), T("M/d/yyyy h:mm tt"))
|
||||||
} | </li>
|
} | </li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -188,6 +188,10 @@ namespace Orchard.Setup {
|
|||||||
public string BaseUrl {
|
public string BaseUrl {
|
||||||
get { return ""; }
|
get { return ""; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string SiteTimeZone {
|
||||||
|
get { return TimeZoneInfo.Local.Id; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,10 +50,6 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Autofac.Integration.Web.Mvc, Version=2.1.13.813, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.Mvc.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\aspnetmvc\Microsoft.Web.Infrastructure.dll</HintPath>
|
<HintPath>..\..\lib\aspnetmvc\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||||
|
|||||||
@@ -193,27 +193,22 @@ namespace Orchard.ContentManagement {
|
|||||||
sb.Append(join.Item2.Type).Append(" ").Append(join.Item1.Name + "." + join.Item2.TableName).Append(" as ").Append(join.Item2.Name).AppendLine();
|
sb.Append(join.Item2.Type).Append(" ").Append(join.Item1.Name + "." + join.Item2.TableName).Append(" as ").Append(join.Item2.Name).AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Where
|
// generating where clause
|
||||||
|
if (_wheres.Any()) {
|
||||||
|
sb.Append("where ");
|
||||||
|
|
||||||
bool first = true;
|
var expressions = new List<string>();
|
||||||
foreach (var where in _wheres) {
|
|
||||||
if (!first) {
|
foreach (var where in _wheres) {
|
||||||
sb.Append("and ");
|
var expressionFactory = new DefaultHqlExpressionFactory();
|
||||||
}
|
where.Item2(expressionFactory);
|
||||||
else {
|
expressions.Add(expressionFactory.Criterion.ToHql(where.Item1));
|
||||||
sb.Append("where ");
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var expressionFactory = new DefaultHqlExpressionFactory();
|
sb.Append("(").Append(String.Join(") AND (", expressions.ToArray())).Append(")").AppendLine();
|
||||||
where.Item2(expressionFactory);
|
|
||||||
sb.Append(expressionFactory.Criterion.ToHql(where.Item1)).AppendLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
// generating order by clause
|
||||||
|
|
||||||
#region Order by
|
|
||||||
|
|
||||||
bool firstSort = true;
|
bool firstSort = true;
|
||||||
foreach (var sort in _sortings) {
|
foreach (var sort in _sortings) {
|
||||||
if (!firstSort) {
|
if (!firstSort) {
|
||||||
@@ -238,8 +233,6 @@ namespace Orchard.ContentManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,8 +48,17 @@ namespace Orchard.Environment.AutofacUtil {
|
|||||||
get { return _lifetimeScope.Tag; }
|
get { return _lifetimeScope.Tag; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<LifetimeScopeBeginningEventArgs> ChildLifetimeScopeBeginning;
|
event EventHandler<LifetimeScopeBeginningEventArgs> ILifetimeScope.ChildLifetimeScopeBeginning {
|
||||||
public event EventHandler<LifetimeScopeEndingEventArgs> CurrentScopeEnding;
|
add { _lifetimeScope.ChildLifetimeScopeBeginning += value; }
|
||||||
public event EventHandler<ResolveOperationBeginningEventArgs> ResolveOperationBeginning;
|
remove { _lifetimeScope.ChildLifetimeScopeBeginning -= value; }
|
||||||
|
}
|
||||||
|
event EventHandler<LifetimeScopeEndingEventArgs> ILifetimeScope.CurrentScopeEnding {
|
||||||
|
add { _lifetimeScope.CurrentScopeEnding += value; }
|
||||||
|
remove { _lifetimeScope.CurrentScopeEnding -= value; }
|
||||||
|
}
|
||||||
|
event EventHandler<ResolveOperationBeginningEventArgs> ILifetimeScope.ResolveOperationBeginning {
|
||||||
|
add { _lifetimeScope.ResolveOperationBeginning += value; }
|
||||||
|
remove { _lifetimeScope.ResolveOperationBeginning -= value; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,6 +80,8 @@ namespace Orchard.Environment.Extensions.Compilers {
|
|||||||
context.AssemblyBuilder.AddAssemblyReference(assembly);
|
context.AssemblyBuilder.AddAssemblyReference(assembly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_criticalErrorProvider.Clear();
|
||||||
|
|
||||||
// Load references specified in project file (only the ones not yet loaded)
|
// Load references specified in project file (only the ones not yet loaded)
|
||||||
foreach (var assemblyReference in projectFileDescriptor.References) {
|
foreach (var assemblyReference in projectFileDescriptor.References) {
|
||||||
if (addedReferences.Contains(assemblyReference.SimpleName))
|
if (addedReferences.Contains(assemblyReference.SimpleName))
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ using Orchard.Localization;
|
|||||||
|
|
||||||
namespace Orchard.Environment.Extensions {
|
namespace Orchard.Environment.Extensions {
|
||||||
public class DefaultCriticalErrorProvider : ICriticalErrorProvider {
|
public class DefaultCriticalErrorProvider : ICriticalErrorProvider {
|
||||||
private readonly ConcurrentBag<LocalizedString> _errorMessages;
|
private ConcurrentBag<LocalizedString> _errorMessages;
|
||||||
|
private readonly object _synLock = new object();
|
||||||
|
|
||||||
public DefaultCriticalErrorProvider() {
|
public DefaultCriticalErrorProvider() {
|
||||||
_errorMessages = new ConcurrentBag<LocalizedString>();
|
_errorMessages = new ConcurrentBag<LocalizedString>();
|
||||||
@@ -22,5 +23,11 @@ namespace Orchard.Environment.Extensions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear() {
|
||||||
|
lock (_synLock) {
|
||||||
|
_errorMessages = new ConcurrentBag<LocalizedString>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,11 @@ namespace Orchard.Environment.Extensions {
|
|||||||
/// Called by any to notice the system of a critical issue at the system level, e.g. incorrect extensions
|
/// Called by any to notice the system of a critical issue at the system level, e.g. incorrect extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void RegisterErrorMessage(LocalizedString message);
|
void RegisterErrorMessage(LocalizedString message);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all error message
|
||||||
|
/// </summary>
|
||||||
|
void Clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,13 +109,13 @@ namespace Orchard.Environment.Features {
|
|||||||
|
|
||||||
IDictionary<FeatureDescriptor, bool> availableFeatures = GetAvailableFeatures()
|
IDictionary<FeatureDescriptor, bool> availableFeatures = GetAvailableFeatures()
|
||||||
.ToDictionary(featureDescriptor => featureDescriptor,
|
.ToDictionary(featureDescriptor => featureDescriptor,
|
||||||
featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name == featureDescriptor.Id) != null);
|
featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name.Equals(featureDescriptor.Id)) != null);
|
||||||
|
|
||||||
IEnumerable<string> featuresToDisable = featureIds
|
IEnumerable<string> featuresToDisable = featureIds
|
||||||
.Select(featureId => DisableFeature(featureId, availableFeatures, force)).ToList()
|
.Select(featureId => DisableFeature(featureId, availableFeatures, force)).ToList()
|
||||||
.SelectMany(ies => ies.Select(s => s));
|
.SelectMany(ies => ies.Select(s => s));
|
||||||
|
|
||||||
if (featuresToDisable.Count() > 0) {
|
if (featuresToDisable.Any()) {
|
||||||
foreach (string featureId in featuresToDisable) {
|
foreach (string featureId in featuresToDisable) {
|
||||||
string id = featureId;
|
string id = featureId;
|
||||||
|
|
||||||
@@ -141,11 +141,11 @@ namespace Orchard.Environment.Features {
|
|||||||
var getDisabledDependencies =
|
var getDisabledDependencies =
|
||||||
new Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>>(
|
new Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>>(
|
||||||
(currentFeatureId, featuresState) => {
|
(currentFeatureId, featuresState) => {
|
||||||
KeyValuePair<FeatureDescriptor, bool> feature = featuresState.Single(featureState => featureState.Key.Id == currentFeatureId);
|
KeyValuePair<FeatureDescriptor, bool> feature = featuresState.Single(featureState => featureState.Key.Id.Equals(currentFeatureId, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
// Retrieve disabled dependencies for the current feature
|
// Retrieve disabled dependencies for the current feature
|
||||||
return feature.Key.Dependencies
|
return feature.Key.Dependencies
|
||||||
.Select(fId => featuresState.Single(featureState => featureState.Key.Id == fId))
|
.Select(fId => featuresState.Single(featureState => featureState.Key.Id.Equals(fId, StringComparison.OrdinalIgnoreCase)))
|
||||||
.Where(featureState => !featureState.Value)
|
.Where(featureState => !featureState.Value)
|
||||||
.ToDictionary(f => f.Key, f => f.Value);
|
.ToDictionary(f => f.Key, f => f.Value);
|
||||||
});
|
});
|
||||||
@@ -173,7 +173,7 @@ namespace Orchard.Environment.Features {
|
|||||||
private IEnumerable<string> DisableFeature(string featureId, IDictionary<FeatureDescriptor, bool> availableFeatures, bool force) {
|
private IEnumerable<string> DisableFeature(string featureId, IDictionary<FeatureDescriptor, bool> availableFeatures, bool force) {
|
||||||
var getEnabledDependants =
|
var getEnabledDependants =
|
||||||
new Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>>(
|
new Func<string, IDictionary<FeatureDescriptor, bool>, IDictionary<FeatureDescriptor, bool>>(
|
||||||
(currentFeatureId, fs) => fs.Where(f => f.Value && f.Key.Dependencies != null && f.Key.Dependencies.Contains(currentFeatureId))
|
(currentFeatureId, fs) => fs.Where(f => f.Value && f.Key.Dependencies != null && f.Key.Dependencies.Select(s => s.ToLowerInvariant()).Contains(currentFeatureId.ToLowerInvariant()))
|
||||||
.ToDictionary(f => f.Key, f => f.Value));
|
.ToDictionary(f => f.Key, f => f.Value));
|
||||||
|
|
||||||
IEnumerable<string> featuresToDisable = GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
|
IEnumerable<string> featuresToDisable = GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
|
||||||
|
|||||||
@@ -165,28 +165,6 @@ namespace Orchard.Mvc.Html {
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Format Date/Time
|
|
||||||
|
|
||||||
public static LocalizedString DateTime(this HtmlHelper htmlHelper, DateTime? value, LocalizedString defaultIfNull) {
|
|
||||||
return value.HasValue ? htmlHelper.DateTime(value.Value) : defaultIfNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LocalizedString DateTime(this HtmlHelper htmlHelper, DateTime? value, LocalizedString defaultIfNull, LocalizedString customFormat) {
|
|
||||||
return value.HasValue ? htmlHelper.DateTime(value.Value, customFormat) : defaultIfNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LocalizedString DateTime(this HtmlHelper htmlHelper, DateTime value) {
|
|
||||||
//TODO: (erikpo) This default format should come from a site setting
|
|
||||||
return htmlHelper.DateTime(value.ToLocalTime(), new LocalizedString("MMM d yyyy h:mm tt")); //todo: above comment and get rid of just wrapping this as a localized string
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LocalizedString DateTime(this HtmlHelper htmlHelper, DateTime value, LocalizedString customFormat) {
|
|
||||||
//TODO: (erikpo) In the future, convert this to "local" time before calling ToString
|
|
||||||
return new LocalizedString(value.ToString(customFormat.Text));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Image
|
#region Image
|
||||||
|
|
||||||
public static MvcHtmlString Image(this HtmlHelper htmlHelper, string src, string alt, object htmlAttributes) {
|
public static MvcHtmlString Image(this HtmlHelper htmlHelper, string src, string alt, object htmlAttributes) {
|
||||||
|
|||||||
@@ -68,11 +68,6 @@
|
|||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Autofac.Integration.Web.Mvc, Version=2.1.13.813, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\..\lib\autofac\Autofac.Integration.Web.Mvc.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Castle.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
<Reference Include="Castle.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
|
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
|
||||||
@@ -276,10 +271,16 @@
|
|||||||
<Compile Include="Security\IEncryptionService.cs" />
|
<Compile Include="Security\IEncryptionService.cs" />
|
||||||
<Compile Include="Security\CurrentUserWorkContext.cs" />
|
<Compile Include="Security\CurrentUserWorkContext.cs" />
|
||||||
<Compile Include="Security\Providers\DefaultEncryptionService.cs" />
|
<Compile Include="Security\Providers\DefaultEncryptionService.cs" />
|
||||||
|
<Compile Include="Services\Clock.cs" />
|
||||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||||
<Compile Include="Themes\CurrentThemeWorkContext.cs" />
|
<Compile Include="Themes\CurrentThemeWorkContext.cs" />
|
||||||
<Compile Include="Themes\ThemeManager.cs" />
|
<Compile Include="Themes\ThemeManager.cs" />
|
||||||
|
<Compile Include="Time\CurrentTimeZoneWorkContext.cs" />
|
||||||
|
<Compile Include="Time\FallbackTimeZoneSelector.cs" />
|
||||||
|
<Compile Include="Time\ITimeZoneSelector.cs" />
|
||||||
|
<Compile Include="Time\SiteTimeZoneSelector.cs" />
|
||||||
|
<Compile Include="Time\TimeZoneSelectorResult.cs" />
|
||||||
<Compile Include="UI\FlatPositionComparer.cs" />
|
<Compile Include="UI\FlatPositionComparer.cs" />
|
||||||
<Compile Include="UI\Navigation\Pager.cs" />
|
<Compile Include="UI\Navigation\Pager.cs" />
|
||||||
<Compile Include="UI\Navigation\PagerParameters.cs" />
|
<Compile Include="UI\Navigation\PagerParameters.cs" />
|
||||||
@@ -884,7 +885,7 @@
|
|||||||
<Compile Include="Security\Permissions\IPermissionProvider.cs" />
|
<Compile Include="Security\Permissions\IPermissionProvider.cs" />
|
||||||
<Compile Include="Security\Permissions\Permission.cs" />
|
<Compile Include="Security\Permissions\Permission.cs" />
|
||||||
<Compile Include="Security\Providers\OrchardRoleProvider.cs" />
|
<Compile Include="Security\Providers\OrchardRoleProvider.cs" />
|
||||||
<Compile Include="Services\Clock.cs" />
|
<Compile Include="Services\IClock.cs" />
|
||||||
<Compile Include="FileSystems\Media\IStorageFile.cs" />
|
<Compile Include="FileSystems\Media\IStorageFile.cs" />
|
||||||
<Compile Include="FileSystems\Media\IStorageFolder.cs" />
|
<Compile Include="FileSystems\Media\IStorageFolder.cs" />
|
||||||
<Compile Include="FileSystems\Media\IStorageProvider.cs" />
|
<Compile Include="FileSystems\Media\IStorageProvider.cs" />
|
||||||
|
|||||||
@@ -2,20 +2,6 @@
|
|||||||
using Orchard.Caching;
|
using Orchard.Caching;
|
||||||
|
|
||||||
namespace Orchard.Services {
|
namespace Orchard.Services {
|
||||||
public interface IClock : IVolatileProvider {
|
|
||||||
DateTime UtcNow { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Each retrieved value is cached during the specified amount of time.
|
|
||||||
/// </summary>
|
|
||||||
IVolatileToken When(TimeSpan duration);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cache is active until the specified time. Each subsequent access won't be cached.
|
|
||||||
/// </summary>
|
|
||||||
IVolatileToken WhenUtc(DateTime absoluteUtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Clock : IClock {
|
public class Clock : IClock {
|
||||||
public DateTime UtcNow {
|
public DateTime UtcNow {
|
||||||
get { return DateTime.UtcNow; }
|
get { return DateTime.UtcNow; }
|
||||||
|
|||||||
56
src/Orchard/Services/IClock.cs
Normal file
56
src/Orchard/Services/IClock.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using Orchard.Caching;
|
||||||
|
|
||||||
|
namespace Orchard.Services {
|
||||||
|
/// <summary>
|
||||||
|
/// Provides the current Utc <see cref="DateTime"/>, and time related method for cache management.
|
||||||
|
/// This service should be used whenever the current date and time are needed, instead of <seealso cref="DateTime"/> directly.
|
||||||
|
/// It also makes implementations more testable, as time can be mocked.
|
||||||
|
/// </summary>
|
||||||
|
public interface IClock : IVolatileProvider {
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current <see cref="DateTime"/> of the system, expressed in Utc
|
||||||
|
/// </summary>
|
||||||
|
DateTime UtcNow { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a <see cref="IVolatileToken"/> instance which can be used to cache some information for a
|
||||||
|
/// specific duration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="duration">The duration that the token must be valid.</param>
|
||||||
|
/// <example>
|
||||||
|
/// This sample shows how to use the <see cref="When"/> method by returning the result of
|
||||||
|
/// a method named LoadVotes(), which is computed every 10 minutes only.
|
||||||
|
/// <code>
|
||||||
|
/// _cacheManager.Get("votes",
|
||||||
|
/// ctx => {
|
||||||
|
/// ctx.Monitor(_clock.When(TimeSpan.FromMinutes(10)));
|
||||||
|
/// return LoadVotes();
|
||||||
|
/// });
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
IVolatileToken When(TimeSpan duration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a <see cref="IVolatileToken"/> instance which can be used to cache some
|
||||||
|
/// until a specific date and time.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="absoluteUtc">The date and time that the token must be valid until.</param>
|
||||||
|
/// <example>
|
||||||
|
/// This sample shows how to use the <see cref="WhenUtc"/> method by returning the result of
|
||||||
|
/// a method named LoadVotes(), which is computed once, and no more until the end of the year.
|
||||||
|
/// <code>
|
||||||
|
/// var endOfYear = _clock.UtcNow;
|
||||||
|
/// endOfYear.Month = 12;
|
||||||
|
/// endOfYear.Day = 31;
|
||||||
|
///
|
||||||
|
/// _cacheManager.Get("votes",
|
||||||
|
/// ctx => {
|
||||||
|
/// ctx.Monitor(_clock.WhenUtc(endOfYear));
|
||||||
|
/// return LoadVotes();
|
||||||
|
/// });
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
IVolatileToken WhenUtc(DateTime absoluteUtc);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Orchard.ContentManagement;
|
using System;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
|
||||||
namespace Orchard.Settings {
|
namespace Orchard.Settings {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -14,5 +15,6 @@ namespace Orchard.Settings {
|
|||||||
ResourceDebugMode ResourceDebugMode { get; set; }
|
ResourceDebugMode ResourceDebugMode { get; set; }
|
||||||
int PageSize { get; set; }
|
int PageSize { get; set; }
|
||||||
string BaseUrl { get; }
|
string BaseUrl { get; }
|
||||||
|
string SiteTimeZone { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/Orchard/Time/CurrentTimeZoneWorkContext.cs
Normal file
35
src/Orchard/Time/CurrentTimeZoneWorkContext.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Orchard.Time {
|
||||||
|
public class CurrentTimeZoneWorkContext : IWorkContextStateProvider {
|
||||||
|
private readonly IEnumerable<ITimeZoneSelector> _timeZoneSelectors;
|
||||||
|
|
||||||
|
public CurrentTimeZoneWorkContext(IEnumerable<ITimeZoneSelector> timeZoneSelectors) {
|
||||||
|
_timeZoneSelectors = timeZoneSelectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Func<WorkContext, T> Get<T>(string name) {
|
||||||
|
if (name == "CurrentTimeZone") {
|
||||||
|
return ctx => (T)(object)CurrentTimeZone(ctx.HttpContext);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeZoneInfo CurrentTimeZone(HttpContextBase httpContext) {
|
||||||
|
var timeZone = _timeZoneSelectors
|
||||||
|
.Select(x => x.GetTimeZone(httpContext))
|
||||||
|
.Where(x => x != null)
|
||||||
|
.OrderByDescending(x => x.Priority)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (timeZone == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeZone.TimeZone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/Orchard/Time/FallbackTimeZoneSelector.cs
Normal file
16
src/Orchard/Time/FallbackTimeZoneSelector.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Orchard.Time {
|
||||||
|
/// <summary>
|
||||||
|
/// Implements <see cref="ITimeZoneSelector"/> by providing the timezone defined in the machine's local settings.
|
||||||
|
/// </summary>
|
||||||
|
public class FallbackTimeZoneSelector : ITimeZoneSelector {
|
||||||
|
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
|
||||||
|
return new TimeZoneSelectorResult {
|
||||||
|
Priority = -100,
|
||||||
|
TimeZone = TimeZoneInfo.Local
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/Orchard/Time/ITimeZoneSelector.cs
Normal file
7
src/Orchard/Time/ITimeZoneSelector.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Orchard.Time {
|
||||||
|
public interface ITimeZoneSelector : IDependency {
|
||||||
|
TimeZoneSelectorResult GetTimeZone(HttpContextBase context);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/Orchard/Time/SiteTimeZoneSelector.cs
Normal file
28
src/Orchard/Time/SiteTimeZoneSelector.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Orchard.Time {
|
||||||
|
/// <summary>
|
||||||
|
/// Implements <see cref="ITimeZoneSelector"/> by providing the timezone defined in the sites settings.
|
||||||
|
/// </summary>
|
||||||
|
public class SiteTimeZoneSelector : ITimeZoneSelector {
|
||||||
|
private readonly IWorkContextAccessor _workContextAccessor;
|
||||||
|
|
||||||
|
public SiteTimeZoneSelector(IWorkContextAccessor workContextAccessor) {
|
||||||
|
_workContextAccessor = workContextAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
|
||||||
|
var siteTimeZoneId = _workContextAccessor.GetContext(context).CurrentSite.SiteTimeZone;
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(siteTimeZoneId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TimeZoneSelectorResult {
|
||||||
|
Priority = -5,
|
||||||
|
TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/Orchard/Time/TimeZoneSelectorResult.cs
Normal file
8
src/Orchard/Time/TimeZoneSelectorResult.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Orchard.Time {
|
||||||
|
public class TimeZoneSelectorResult {
|
||||||
|
public int Priority { get; set; }
|
||||||
|
public TimeZoneInfo TimeZone { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -192,7 +192,7 @@ namespace Orchard.UI.Resources {
|
|||||||
if (!String.IsNullOrEmpty(settings.Culture)) {
|
if (!String.IsNullOrEmpty(settings.Culture)) {
|
||||||
string nearestCulture = FindNearestCulture(settings.Culture);
|
string nearestCulture = FindNearestCulture(settings.Culture);
|
||||||
if (!String.IsNullOrEmpty(nearestCulture)) {
|
if (!String.IsNullOrEmpty(nearestCulture)) {
|
||||||
url = Path.ChangeExtension(url, nearestCulture + "." + Path.GetExtension(url));
|
url = Path.ChangeExtension(url, nearestCulture + Path.GetExtension(url));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute) && !VirtualPathUtility.IsAbsolute(url) && !VirtualPathUtility.IsAppRelative(url) && !String.IsNullOrEmpty(BasePath)) {
|
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute) && !VirtualPathUtility.IsAbsolute(url) && !VirtualPathUtility.IsAppRelative(url) && !String.IsNullOrEmpty(BasePath)) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Web;
|
using System;
|
||||||
|
using System.Web;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
using Orchard.Security;
|
using Orchard.Security;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
@@ -75,5 +76,13 @@ namespace Orchard {
|
|||||||
get { return GetState<string>("CurrentCulture"); }
|
get { return GetState<string>("CurrentCulture"); }
|
||||||
set { SetState("CurrentCulture", value); }
|
set { SetState("CurrentCulture", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Time zone of the work context
|
||||||
|
/// </summary>
|
||||||
|
public TimeZoneInfo CurrentTimeZone {
|
||||||
|
get { return GetState<TimeZoneInfo>("CurrentTimeZone"); }
|
||||||
|
set { SetState("CurrentTimeZone", value); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user