mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Merge branch 'dev' of https://github.com/OrchardCMS/Orchard into replace-lib-with-nuget
Conflicts: src/Orchard.Web/Core/Orchard.Core.csproj src/Orchard.Web/Modules/Orchard.Fields/Orchard.Fields.csproj
This commit is contained in:
commit
89f0213a78
3
.gitignore
vendored
3
.gitignore
vendored
@ -186,5 +186,6 @@ src/Orchard.Web/Properties/PublishProfiles
|
||||
src/Orchard.Azure/Orchard.Azure.CloudService/Staging/
|
||||
|
||||
#enable all /lib artifacts
|
||||
!lib/*/*.*
|
||||
!lib/**/*.*
|
||||
!src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Lib/*.*
|
||||
*/.vs/*
|
||||
|
@ -19,6 +19,7 @@ namespace Orchard.Tests.Environment {
|
||||
}
|
||||
|
||||
protected override void Register(ContainerBuilder builder) {
|
||||
builder.RegisterModule(new MvcModule());
|
||||
builder.RegisterModule(new WorkContextModule());
|
||||
builder.RegisterType<WorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterAutoMocking();
|
||||
|
@ -21,6 +21,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<ShellContextFactory>().As<IShellContextFactory>();
|
||||
builder.RegisterModule(new MvcModule());
|
||||
builder.RegisterModule(new WorkContextModule());
|
||||
builder.RegisterType<WorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterAutoMocking(Moq.MockBehavior.Strict);
|
||||
@ -93,4 +94,4 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
Assert.That(context.Descriptor.Features, Has.Some.With.Property("Name").EqualTo("Orchard.Setup"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace Orchard.Tests.Tasks {
|
||||
public class SweepGeneratorTests : ContainerTestBase {
|
||||
protected override void Register(ContainerBuilder builder) {
|
||||
builder.RegisterAutoMocking(MockBehavior.Loose);
|
||||
builder.RegisterModule(new MvcModule());
|
||||
builder.RegisterModule(new WorkContextModule());
|
||||
builder.RegisterType<WorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterType<SweepGenerator>();
|
||||
|
@ -72,7 +72,14 @@ namespace Orchard.Core.Common.Drivers {
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Fields.Common.Text.Edit", Model: viewModel, Prefix: GetPrefix(field, part)));
|
||||
}
|
||||
|
||||
field.Value = viewModel.Text;
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<TextFieldSettings>();
|
||||
|
||||
if (String.IsNullOrEmpty(field.Value) && !String.IsNullOrEmpty(settings.DefaultValue)) {
|
||||
field.Value = settings.DefaultValue;
|
||||
}
|
||||
else {
|
||||
field.Value = viewModel.Text;
|
||||
}
|
||||
}
|
||||
|
||||
return Editor(part, field, shapeHelper);
|
||||
|
@ -7,5 +7,6 @@ namespace Orchard.Core.Common.Settings {
|
||||
public string Flavor { get; set; }
|
||||
public bool Required { get; set; }
|
||||
public string Hint { get; set; }
|
||||
public string DefaultValue { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ namespace Orchard.Core.Common.Settings {
|
||||
builder.WithSetting("TextFieldSettings.Flavor", model.Settings.Flavor);
|
||||
builder.WithSetting("TextFieldSettings.Hint", model.Settings.Hint);
|
||||
builder.WithSetting("TextFieldSettings.Required", model.Settings.Required.ToString(CultureInfo.InvariantCulture));
|
||||
builder.WithSetting("TextFieldSettings.DefaultValue", model.Settings.DefaultValue);
|
||||
|
||||
yield return DefinitionTemplate(model);
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
@model Orchard.Core.Common.ViewModels.TextFieldSettingsEventsViewModel
|
||||
|
||||
@* This is a token-less default value editor that can be overridden from features that can depend on Orchard.Tokens. *@
|
||||
|
||||
<label for="@Html.FieldIdFor(m => m.Settings.DefaultValue)">@T("Default value")</label>
|
||||
@Html.TextBoxFor(m => m.Settings.DefaultValue, new { @class = "text large" })
|
||||
<span class="hint">@T("Default value for the field. If there is no value given for the actual field, this will be filled in. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.Settings.DefaultValue)
|
@ -18,4 +18,7 @@
|
||||
@Html.TextAreaFor(m => m.Settings.Hint, new { @class = "text medium", rows = "5" })
|
||||
<span class="hint">@T("The help text is written under the field when authors are editing the content item.")</span>
|
||||
@Html.ValidationMessageFor(m => m.Settings.Hint)
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
@Display.DefinitionTemplate(TemplateName: "TextFieldDefaultValueEditor", Model: Model)
|
||||
</fieldset>
|
@ -12,4 +12,7 @@
|
||||
@if (HasText(Model.Settings.Hint)) {
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
}
|
||||
</fieldset>
|
||||
@if (!String.IsNullOrWhiteSpace(Model.Settings.DefaultValue)) {
|
||||
<span class="hint">@T("If the field is left empty then the default value will be used.")</span>
|
||||
}
|
||||
</fieldset>
|
@ -599,6 +599,9 @@
|
||||
<ItemGroup>
|
||||
<Content Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Common\Views\DefinitionTemplates\TextFieldDefaultValueEditor.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
@ -799,6 +799,11 @@ namespace Orchard.Core.Shapes {
|
||||
RenderInternal(Html, Output, "EditorTemplates/" + TemplateName, Model, Prefix);
|
||||
}
|
||||
|
||||
[Shape]
|
||||
public void DefinitionTemplate(HtmlHelper Html, TextWriter Output, string TemplateName, object Model, string Prefix) {
|
||||
RenderInternal(Html, Output, "DefinitionTemplates/" + TemplateName, Model, Prefix);
|
||||
}
|
||||
|
||||
static void RenderInternal(HtmlHelper Html, TextWriter Output, string TemplateName, object Model, string Prefix) {
|
||||
var adjustedViewData = new ViewDataDictionary(Html.ViewDataContainer.ViewData) {
|
||||
Model = DetermineModel(Html, Model),
|
||||
|
@ -68,9 +68,7 @@ namespace Orchard.Blogs {
|
||||
ContentDefinitionManager.AlterTypeDefinition("RecentBlogPosts",
|
||||
cfg => cfg
|
||||
.WithPart("RecentBlogPostsPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.AsWidgetWithIdentity()
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterPartDefinition("BlogArchivesPart", part => part
|
||||
@ -134,6 +132,11 @@ namespace Orchard.Blogs {
|
||||
}
|
||||
|
||||
public int UpdateFrom6() {
|
||||
ContentDefinitionManager.AlterTypeDefinition("RecentBlogPosts",
|
||||
cfg => cfg
|
||||
.WithPart("IdentityPart")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("BlogArchives",
|
||||
cfg => cfg
|
||||
.WithPart("IdentityPart")
|
||||
|
@ -191,6 +191,10 @@
|
||||
<Project>{f301ef7d-f19c-4d83-aa94-cb64f29c037d}</Project>
|
||||
<Name>Orchard.ContentPicker</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Widgets\Orchard.Widgets.csproj">
|
||||
<Project>{194d3ccc-1153-474d-8176-fde8d7d0d0bd}</Project>
|
||||
<Name>Orchard.Widgets</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Placement.info">
|
||||
|
@ -56,15 +56,14 @@ namespace Orchard.DynamicForms {
|
||||
.Draftable());
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("FormWidget", type => type
|
||||
.AsWidgetWithIdentity()
|
||||
.WithPart("LayoutPart", p => p
|
||||
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||
.WithPart("CommonPart", p => p
|
||||
.WithSetting("OwnerEditorSettings.ShowOwnerEditor", "false")
|
||||
.WithSetting("DateEditorSettings.ShowDateEditor", "false"))
|
||||
.WithPart("WidgetPart")
|
||||
.WithPart("LayoutPart", p => p
|
||||
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.DisplayedAs("Form Widget"));
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
public int UpdateFrom1() {
|
||||
@ -107,6 +106,13 @@ namespace Orchard.DynamicForms {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int UpdateFrom2() {
|
||||
ContentDefinitionManager.AlterTypeDefinition("FormWidget", type => type
|
||||
.WithPart("IdentityPart"));
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
private byte[] GetMD5(string text) {
|
||||
byte[] encodedText = System.Text.Encoding.UTF8.GetBytes(text);
|
||||
return ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedText);
|
||||
|
@ -174,6 +174,10 @@
|
||||
<Project>{79aed36e-abd0-4747-93d3-8722b042454b}</Project>
|
||||
<Name>Orchard.Users</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Widgets\Orchard.Widgets.csproj">
|
||||
<Project>{194d3ccc-1153-474d-8176-fde8d7d0d0bd}</Project>
|
||||
<Name>Orchard.Widgets</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Workflows\Orchard.Workflows.csproj">
|
||||
<Project>{7059493c-8251-4764-9c1e-2368b8b485bc}</Project>
|
||||
<Name>Orchard.Workflows</Name>
|
||||
|
@ -1,16 +1,15 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Fields.Fields;
|
||||
using Orchard.Fields.Settings;
|
||||
using Orchard.Fields.ViewModels;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Localization.Models;
|
||||
using Orchard.Localization.Services;
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace Orchard.Fields.Drivers {
|
||||
public class DateTimeFieldDriver : ContentFieldDriver<DateTimeField> {
|
||||
@ -97,6 +96,7 @@ namespace Orchard.Fields.Drivers {
|
||||
Name = field.DisplayName,
|
||||
Hint = settings.Hint,
|
||||
IsRequired = settings.Required,
|
||||
HasDefaultValue = settings.DefaultValue.HasValue,
|
||||
Editor = new DateTimeEditor() {
|
||||
Date = showDate ? DateLocalizationServices.ConvertToLocalizedDateString(value, options) : null,
|
||||
Time = showTime ? DateLocalizationServices.ConvertToLocalizedTimeString(value, options) : null,
|
||||
@ -150,7 +150,7 @@ namespace Orchard.Fields.Drivers {
|
||||
field.DateTime = utcDateTime.Value;
|
||||
}
|
||||
} else {
|
||||
field.DateTime = DateTime.MinValue;
|
||||
field.DateTime = settings.DefaultValue.HasValue ? settings.DefaultValue.Value : DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
@ -1,18 +1,22 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Fields.Settings;
|
||||
using Orchard.Fields.Fields;
|
||||
using Orchard.Fields.Settings;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Fields.Drivers {
|
||||
public class EnumerationFieldDriver : ContentFieldDriver<EnumerationField> {
|
||||
public IOrchardServices Services { get; set; }
|
||||
private const string TemplateName = "Fields/Enumeration.Edit";
|
||||
private readonly ITokenizer _tokenizer;
|
||||
|
||||
public EnumerationFieldDriver(IOrchardServices services) {
|
||||
public EnumerationFieldDriver(IOrchardServices services, ITokenizer tokenizer) {
|
||||
Services = services;
|
||||
_tokenizer = tokenizer;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@ -33,7 +37,16 @@ namespace Orchard.Fields.Drivers {
|
||||
|
||||
protected override DriverResult Editor(ContentPart part, EnumerationField field, dynamic shapeHelper) {
|
||||
return ContentShape("Fields_Enumeration_Edit", GetDifferentiator(field, part),
|
||||
() => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: field, Prefix: GetPrefix(field, part)));
|
||||
() => {
|
||||
if (field.Value == null) {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<EnumerationFieldSettings>();
|
||||
if (!String.IsNullOrEmpty(settings.DefaultValue)) {
|
||||
field.Value = _tokenizer.Replace(settings.DefaultValue, new Dictionary<string, object> { { "Content", part.ContentItem } });
|
||||
}
|
||||
}
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: field, Prefix: GetPrefix(field, part));
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ContentPart part, EnumerationField field, IUpdateModel updater, dynamic shapeHelper) {
|
||||
|
@ -1,19 +1,22 @@
|
||||
using System;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Fields.Fields;
|
||||
using Orchard.Fields.Settings;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Utility.Extensions;
|
||||
using Orchard.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Fields.Drivers {
|
||||
public class InputFieldDriver : ContentFieldDriver<InputField> {
|
||||
public IOrchardServices Services { get; set; }
|
||||
private const string TemplateName = "Fields/Input.Edit";
|
||||
private readonly ITokenizer _tokenizer;
|
||||
|
||||
public InputFieldDriver(IOrchardServices services) {
|
||||
public InputFieldDriver(IOrchardServices services, ITokenizer tokenizer) {
|
||||
Services = services;
|
||||
_tokenizer = tokenizer;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@ -43,6 +46,10 @@ namespace Orchard.Fields.Drivers {
|
||||
if (updater.TryUpdateModel(field, GetPrefix(field, part), null, null)) {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<InputFieldSettings>();
|
||||
|
||||
if (field.Value == null && !String.IsNullOrEmpty(settings.DefaultValue)) {
|
||||
field.Value = _tokenizer.Replace(settings.DefaultValue, new Dictionary<string, object> { { "Content", part.ContentItem } });
|
||||
}
|
||||
|
||||
if (settings.Required && string.IsNullOrWhiteSpace(field.Value)) {
|
||||
updater.AddModelError(GetPrefix(field, part), T("The field {0} is mandatory.", T(field.DisplayName)));
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
using System;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Fields.Fields;
|
||||
using Orchard.Fields.Settings;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Fields.Drivers {
|
||||
public class LinkFieldDriver : ContentFieldDriver<LinkField> {
|
||||
public IOrchardServices Services { get; set; }
|
||||
private const string TemplateName = "Fields/Link.Edit";
|
||||
private readonly ITokenizer _tokenizer;
|
||||
|
||||
public LinkFieldDriver(IOrchardServices services) {
|
||||
public LinkFieldDriver(IOrchardServices services, ITokenizer tokenizer) {
|
||||
Services = services;
|
||||
_tokenizer = tokenizer;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@ -41,6 +45,15 @@ namespace Orchard.Fields.Drivers {
|
||||
protected override DriverResult Editor(ContentPart part, LinkField field, IUpdateModel updater, dynamic shapeHelper) {
|
||||
if (updater.TryUpdateModel(field, GetPrefix(field, part), null, null)) {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<LinkFieldSettings>();
|
||||
|
||||
if (String.IsNullOrEmpty(field.Value) && !String.IsNullOrEmpty(settings.DefaultValue)) {
|
||||
field.Value = _tokenizer.Replace(settings.DefaultValue, new Dictionary<string, object> { { "Content", part.ContentItem } });
|
||||
}
|
||||
|
||||
if(!String.IsNullOrEmpty(settings.TextDefaultValue) && String.IsNullOrWhiteSpace(field.Text)) {
|
||||
field.Text = _tokenizer.Replace(settings.TextDefaultValue, new Dictionary<string, object> { { "Content", part.ContentItem } });
|
||||
}
|
||||
|
||||
if (settings.Required && string.IsNullOrWhiteSpace(field.Value)) {
|
||||
updater.AddModelError(GetPrefix(field, part), T("Url is required for {0}", field.DisplayName));
|
||||
}
|
||||
|
@ -1,21 +1,25 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Fields.Fields;
|
||||
using Orchard.Fields.Settings;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Fields.ViewModels;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Orchard.Fields.Drivers {
|
||||
public class NumericFieldDriver : ContentFieldDriver<NumericField> {
|
||||
public IOrchardServices Services { get; set; }
|
||||
private const string TemplateName = "Fields/Numeric.Edit";
|
||||
private readonly Lazy<CultureInfo> _cultureInfo;
|
||||
private readonly ITokenizer _tokenizer;
|
||||
|
||||
public NumericFieldDriver(IOrchardServices services) {
|
||||
public NumericFieldDriver(IOrchardServices services, ITokenizer tokenizer) {
|
||||
Services = services;
|
||||
_tokenizer = tokenizer;
|
||||
T = NullLocalizer.Instance;
|
||||
|
||||
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(Services.WorkContext.CurrentCulture));
|
||||
@ -40,7 +44,6 @@ namespace Orchard.Fields.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ContentPart part, NumericField field, dynamic shapeHelper) {
|
||||
|
||||
return ContentShape("Fields_Numeric_Edit", GetDifferentiator(field, part),
|
||||
() => {
|
||||
var model = new NumericFieldViewModel {
|
||||
@ -66,7 +69,16 @@ namespace Orchard.Fields.Drivers {
|
||||
}
|
||||
|
||||
if (!settings.Required && String.IsNullOrWhiteSpace(viewModel.Value)) {
|
||||
field.Value = null;
|
||||
if (settings.DefaultValue != null) {
|
||||
if (Decimal.TryParse(_tokenizer.Replace(settings.DefaultValue, new Dictionary<string, object> { { "Content", part.ContentItem } }), NumberStyles.Any, _cultureInfo.Value, out value)
|
||||
&& Math.Round(value, settings.Scale) == value
|
||||
&& !String.IsNullOrEmpty(settings.DefaultValue)) {
|
||||
field.Value = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
field.Value = null;
|
||||
}
|
||||
}
|
||||
else if (Decimal.TryParse(viewModel.Value, NumberStyles.Any, _cultureInfo.Value, out value)) {
|
||||
field.Value = value;
|
||||
|
@ -0,0 +1,29 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Common.Fields;
|
||||
using Orchard.Core.Common.Settings;
|
||||
using Orchard.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Fields.Drivers {
|
||||
// The original driver of the TextField is in Orchard.Core, where tokenization can not be used.
|
||||
// This driver was added so the default value of the TextField can be tokenized.
|
||||
public class TextFieldDriver : ContentFieldDriver<TextField> {
|
||||
private readonly ITokenizer _tokenizer;
|
||||
|
||||
public TextFieldDriver(ITokenizer tokenizer) {
|
||||
_tokenizer = tokenizer;
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(ContentPart part, TextField field, IUpdateModel updater, dynamic shapeHelper) {
|
||||
var settings = field.PartFieldDefinition.Settings.GetModel<TextFieldSettings>();
|
||||
|
||||
if (String.IsNullOrEmpty(field.Value) && !String.IsNullOrEmpty(settings.DefaultValue)) {
|
||||
field.Value = _tokenizer.Replace(settings.DefaultValue, new Dictionary<string, object> { { "Content", part.ContentItem } });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,4 +9,4 @@ Features:
|
||||
Orchard.Fields:
|
||||
Description: Contains the following fields: Input, Boolean, DateTime, Numeric, Link, Enumeration
|
||||
Category: Fields
|
||||
Dependencies: Common, Orchard.Resources
|
||||
Dependencies: Common, Orchard.Resources, Orchard.Tokens
|
||||
|
@ -100,6 +100,7 @@
|
||||
<Content Include="Styles\Images\move.gif" />
|
||||
<Content Include="Web.config" />
|
||||
<Content Include="Styles\Web.config" />
|
||||
<Compile Include="Drivers\TextFieldDriver.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Content Include="Module.txt" />
|
||||
</ItemGroup>
|
||||
@ -114,6 +115,10 @@
|
||||
<Name>Orchard.Core</Name>
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Tokens\Orchard.Tokens.csproj">
|
||||
<Project>{6f759635-13d7-4e94-bcc9-80445d63f117}</Project>
|
||||
<Name>Orchard.Tokens</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Placement.info">
|
||||
@ -176,6 +181,9 @@
|
||||
<ItemGroup>
|
||||
<Content Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\DefinitionTemplates\TextFieldDefaultValueEditor.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
@ -1,17 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Localization.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Orchard.Fields.Settings {
|
||||
public class DateTimeFieldEditorEvents : ContentDefinitionEditorEventsBase {
|
||||
private readonly IDateLocalizationServices _dateLocalizationServices;
|
||||
|
||||
public DateTimeFieldEditorEvents(IDateLocalizationServices dateLocalizationServices) {
|
||||
_dateLocalizationServices = dateLocalizationServices;
|
||||
}
|
||||
|
||||
public override IEnumerable<TemplateViewModel> PartFieldEditor(ContentPartFieldDefinition definition) {
|
||||
if (definition.FieldDefinition.Name == "DateTimeField") {
|
||||
var model = definition.Settings.GetModel<DateTimeFieldSettings>();
|
||||
model.Editor = new DateTimeEditor() {
|
||||
ShowDate = true,
|
||||
ShowTime = true,
|
||||
Date = _dateLocalizationServices.ConvertToLocalizedDateString(model.DefaultValue),
|
||||
Time = _dateLocalizationServices.ConvertToLocalizedTimeString(model.DefaultValue),
|
||||
};
|
||||
yield return DefinitionTemplate(model);
|
||||
}
|
||||
}
|
||||
@ -26,6 +40,8 @@ namespace Orchard.Fields.Settings {
|
||||
builder.WithSetting("DateTimeFieldSettings.Display", model.Display.ToString());
|
||||
builder.WithSetting("DateTimeFieldSettings.Hint", model.Hint);
|
||||
builder.WithSetting("DateTimeFieldSettings.Required", model.Required.ToString(CultureInfo.InvariantCulture));
|
||||
model.DefaultValue = model.Editor == null ? model.DefaultValue : _dateLocalizationServices.ConvertFromLocalizedString(model.Editor.Date, model.Editor.Time);
|
||||
builder.WithSetting("DateTimeFieldSettings.DefaultValue", model.DefaultValue.HasValue ? model.DefaultValue.Value.ToString(CultureInfo.InvariantCulture) : String.Empty);
|
||||
|
||||
yield return DefinitionTemplate(model);
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
namespace Orchard.Fields.Settings {
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using System;
|
||||
|
||||
namespace Orchard.Fields.Settings {
|
||||
|
||||
public enum DateTimeFieldDisplays {
|
||||
DateAndTime,
|
||||
@ -10,5 +13,7 @@
|
||||
public DateTimeFieldDisplays Display { get; set; }
|
||||
public string Hint { get; set; }
|
||||
public bool Required { get; set; }
|
||||
public DateTime? DefaultValue { get; set; }
|
||||
public DateTimeEditor Editor { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Orchard.Fields.Settings {
|
||||
public class EnumerationFieldListModeEvents : ContentDefinitionEditorEventsBase {
|
||||
@ -27,6 +27,7 @@ namespace Orchard.Fields.Settings {
|
||||
builder.WithSetting("EnumerationFieldSettings.Required", model.Required.ToString(CultureInfo.InvariantCulture));
|
||||
builder.WithSetting("EnumerationFieldSettings.Options", model.Options);
|
||||
builder.WithSetting("EnumerationFieldSettings.ListMode", model.ListMode.ToString());
|
||||
builder.WithSetting("EnumerationFieldSettings.DefaultValue", model.DefaultValue);
|
||||
}
|
||||
|
||||
yield return DefinitionTemplate(model);
|
||||
|
@ -12,6 +12,7 @@
|
||||
public bool Required { get; set; }
|
||||
public string Options { get; set; }
|
||||
public ListMode ListMode { get; set; }
|
||||
public string DefaultValue { get; set; }
|
||||
|
||||
public EnumerationFieldSettings() {
|
||||
ListMode = ListMode.Dropdown;
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Orchard.Fields.Settings {
|
||||
public class InputFieldListModeEvents : ContentDefinitionEditorEventsBase {
|
||||
@ -32,6 +33,7 @@ namespace Orchard.Fields.Settings {
|
||||
builder.WithSetting("InputFieldSettings.Pattern", model.Pattern);
|
||||
builder.WithSetting("InputFieldSettings.EditorCssClass", model.EditorCssClass);
|
||||
builder.WithSetting("InputFieldSettings.MaxLength", model.MaxLength.ToString());
|
||||
builder.WithSetting("InputFieldSettings.DefaultValue", model.DefaultValue);
|
||||
}
|
||||
|
||||
yield return DefinitionTemplate(model);
|
||||
|
@ -18,6 +18,7 @@
|
||||
public string Pattern { get; set; }
|
||||
public string EditorCssClass { get; set; }
|
||||
public int MaxLength { get; set; }
|
||||
public string DefaultValue { get; set; }
|
||||
|
||||
public InputFieldSettings() {
|
||||
Type = InputType.Text;
|
||||
|
@ -1,10 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Orchard.Fields.Settings {
|
||||
public class LinkFieldListModeEvents : ContentDefinitionEditorEventsBase {
|
||||
@ -28,7 +28,9 @@ namespace Orchard.Fields.Settings {
|
||||
builder.WithSetting("LinkFieldSettings.TargetMode", model.TargetMode.ToString());
|
||||
builder.WithSetting("LinkFieldSettings.LinkTextMode", model.LinkTextMode.ToString());
|
||||
builder.WithSetting("LinkFieldSettings.StaticText", model.StaticText);
|
||||
|
||||
builder.WithSetting("LinkFieldSettings.DefaultValue", model.DefaultValue);
|
||||
builder.WithSetting("LinkFieldSettings.TextDefaultValue", model.TextDefaultValue);
|
||||
|
||||
yield return DefinitionTemplate(model);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
public TargetMode TargetMode { get; set; }
|
||||
public LinkTextMode LinkTextMode { get; set; }
|
||||
public string StaticText { get; set; }
|
||||
public string DefaultValue { get; set; }
|
||||
public string TextDefaultValue { get; set; }
|
||||
|
||||
public LinkFieldSettings() {
|
||||
TargetMode = TargetMode.None;
|
||||
|
@ -1,10 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Orchard.Fields.Settings {
|
||||
public class NumericFieldListModeEvents : ContentDefinitionEditorEventsBase {
|
||||
@ -28,6 +28,7 @@ namespace Orchard.Fields.Settings {
|
||||
builder.WithSetting("NumericFieldSettings.Scale", model.Scale.ToString(CultureInfo.InvariantCulture));
|
||||
builder.WithSetting("NumericFieldSettings.Minimum", model.Minimum.HasValue ? model.Minimum.Value.ToString(CultureInfo.InvariantCulture) : string.Empty);
|
||||
builder.WithSetting("NumericFieldSettings.Maximum", model.Maximum.HasValue ? model.Maximum.Value.ToString(CultureInfo.InvariantCulture) : string.Empty);
|
||||
builder.WithSetting("NumericFieldSettings.DefaultValue", model.DefaultValue);
|
||||
}
|
||||
|
||||
yield return DefinitionTemplate(model);
|
||||
|
@ -5,6 +5,7 @@
|
||||
public int Scale { get; set; }
|
||||
public decimal? Minimum { get; set; }
|
||||
public decimal? Maximum { get; set; }
|
||||
public string DefaultValue { get; set; }
|
||||
|
||||
public NumericFieldSettings() {
|
||||
Scale = 0;
|
||||
|
@ -6,5 +6,6 @@ namespace Orchard.Fields.ViewModels {
|
||||
public string Hint { get; set; }
|
||||
public bool IsRequired { get; set; }
|
||||
public DateTimeEditor Editor { get; set; }
|
||||
public bool HasDefaultValue { get; set; }
|
||||
}
|
||||
}
|
@ -27,3 +27,12 @@
|
||||
@Html.ValidationMessageFor(m => m.Hint)
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.Editor)">@T("Default value")</label>
|
||||
@Html.EditorFor(m => m.Editor)
|
||||
<span class="hint">@T("Pick a default date for the field. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.Editor)
|
||||
</div>
|
||||
</fieldset>
|
||||
|
@ -28,3 +28,11 @@
|
||||
<span class="hint">@T("The help text is written under the field when users are selecting an option.")</span>
|
||||
@Html.ValidationMessageFor(m => m.Hint)
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<label class="forpicker" for="@Html.FieldIdFor(m => m.DefaultValue)">@T("Default value")</label>
|
||||
@Html.TextBoxFor(m => m.DefaultValue, new { @class = "text large tokenized ui-autocomplete-input" })
|
||||
<span class="hint">@T("Enter a default option for the field. You can use tokens in this field. If there is no equivalent choice among Options, it will not be used. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.DefaultValue)
|
||||
</div>
|
||||
</fieldset>
|
@ -77,3 +77,11 @@
|
||||
@Html.ValidationMessageFor(m => m.Hint)
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.DefaultValue)">@T("Default value")</label>
|
||||
@Html.TextBoxFor(m => m.DefaultValue, new { @class = "text large tokenized ui-autocomplete-input" })
|
||||
<span class="hint">@T("A valid url as a default value, i.e. http://orchardproject.net, /content/file.pdf ... You can use tokens in this field. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.DefaultValue)
|
||||
</div>
|
||||
</fieldset>
|
@ -44,3 +44,19 @@
|
||||
@Html.ValidationMessageFor(m => m.Hint)
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.DefaultValue)">@T("Default value")</label>
|
||||
@Html.TextBoxFor(m => m.DefaultValue, new { @class = "text large tokenized ui-autocomplete-input" })
|
||||
<span class="hint">@T("A valid url as a default value, i.e. http://orchardproject.net, /content/file.pdf ... You can use tokens in this field. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.DefaultValue)
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.TextDefaultValue)">@T("Link text default value")</label>
|
||||
@Html.TextBoxFor(m => m.TextDefaultValue, new { @class = "text large tokenized ui-autocomplete-input" })
|
||||
<span class="hint">@T("If the Link text is set to Optional or Required, a default value can be set for it. You can use tokens in this field. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.TextDefaultValue)
|
||||
</div>
|
||||
</fieldset>
|
@ -39,3 +39,11 @@
|
||||
@Html.ValidationMessageFor(m => m.Hint)
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div class="editor-field">
|
||||
<label class="forpicker" for="@Html.FieldIdFor(m => m.DefaultValue)">@T("Default value")</label>
|
||||
@Html.TextBoxFor(m => m.DefaultValue, new { @class = "text large tokenized ui-autocomplete-input" })
|
||||
<span class="hint">@T("The default value for the field. It must be a number, and if not it will not shown. Make sure to set the Scale property if the value is not an integer. You can use tokens in this field. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.DefaultValue)
|
||||
</div>
|
||||
</fieldset>
|
@ -0,0 +1,7 @@
|
||||
@model Orchard.Core.Common.ViewModels.TextFieldSettingsEventsViewModel
|
||||
@* This override is here so that the token helper can be used on the default value's textbox, which can not be used in Orchard.Core. *@
|
||||
|
||||
<label for="@Html.FieldIdFor(m => m.Settings.DefaultValue)">@T("Default value")</label>
|
||||
@Html.TextBoxFor(m => m.Settings.DefaultValue, new { @class = "text large tokenized ui-autocomplete-input" })
|
||||
<span class="hint">@T("Default value for the field. You can use tokens in this field. If there is no value given for the actual field, this will be filled in. (optional)")</span>
|
||||
@Html.ValidationMessageFor(m => m.Settings.DefaultValue)
|
@ -6,4 +6,7 @@
|
||||
@if (HasText(Model.Hint)) {
|
||||
<span class="hint">@Model.Hint</span>
|
||||
}
|
||||
@if (Model.HasDefaultValue) {
|
||||
<span class="hint">@T("If the field is left empty then the default value will be used if one is configured.")</span>
|
||||
}
|
||||
</fieldset>
|
||||
|
@ -11,4 +11,7 @@
|
||||
@if (HasText(settings.Hint)) {
|
||||
<span class="hint">@settings.Hint</span>
|
||||
}
|
||||
@if (!String.IsNullOrWhiteSpace(settings.DefaultValue)) {
|
||||
<span class="hint">@T("If the field is left empty then the default value will be used.")</span>
|
||||
}
|
||||
</fieldset>
|
||||
|
@ -27,13 +27,21 @@
|
||||
@Html.TextBoxFor(m => m.Value, new { @class = "text large" })
|
||||
<span class="hint">@T("A valid url, i.e. http://orchardproject.net, /content/file.pdf, ...")</span>
|
||||
</div>
|
||||
@if (!String.IsNullOrWhiteSpace(settings.DefaultValue)) {
|
||||
<span class="hint">@T("If the field is left empty then the default value will be used.")</span>
|
||||
}
|
||||
@if (settings.LinkTextMode == LinkTextMode.Optional || settings.LinkTextMode == LinkTextMode.Required) {
|
||||
<div class="editor-label">
|
||||
<label for="@Html.FieldIdFor(m => m.Text)" @if(settings.LinkTextMode == LinkTextMode.Required) { <text>class="required"</text> }>@T("Text")</label>
|
||||
</div>
|
||||
<div class="editor-field">
|
||||
@Html.TextBoxFor(m => m.Text, new {@class = "text medium"})
|
||||
<span class="hint">@T("The text of the link. If left empty, the url will be used instead.")</span>
|
||||
@Html.TextBoxFor(m => m.Text, new { @class = "text medium" })
|
||||
@if (!String.IsNullOrWhiteSpace(settings.TextDefaultValue)) {
|
||||
<span class="hint">@T("If the field is left empty then the default value will be used.")</span>
|
||||
}
|
||||
else {
|
||||
<span class="hint">@T("The text of the link. If left empty, the url will be used instead.")</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -11,4 +11,7 @@
|
||||
@if (HasText(Model.Settings.Hint)) {
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
}
|
||||
@if (!String.IsNullOrWhiteSpace(Model.Settings.DefaultValue)) {
|
||||
<span class="hint">@T("If the field is left empty then the default value will be used.")</span>
|
||||
}
|
||||
</fieldset>
|
||||
|
@ -8,18 +8,7 @@
|
||||
controller: ["$scope", "$element",
|
||||
function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
$scope.$apply(function () {
|
||||
if (args.cancel)
|
||||
return;
|
||||
|
||||
$scope.element.data = args.element.data;
|
||||
$scope.element.setHtml(args.element.html);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
|
||||
$scope.element.setHtml = function (html) {
|
||||
$scope.element.html = html;
|
||||
|
@ -1,41 +0,0 @@
|
||||
angular
|
||||
.module("LayoutEditor")
|
||||
.directive("orcLayoutHtml", ["$sce", "scopeConfigurator", "environment",
|
||||
function ($sce, scopeConfigurator, environment) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: { element: "=" },
|
||||
controller: ["$scope", "$element",
|
||||
function ($scope, $element) {
|
||||
scopeConfigurator.configureForElement($scope, $element);
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
$scope.$apply(function () {
|
||||
if (args.cancel)
|
||||
return;
|
||||
|
||||
$scope.element.data = args.element.data;
|
||||
$scope.element.setHtml(args.element.html);
|
||||
});
|
||||
});
|
||||
};
|
||||
$scope.updateContent = function (e) {
|
||||
$scope.element.setHtml(e.target.innerHTML);
|
||||
};
|
||||
|
||||
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
|
||||
$scope.element.setHtml = function (html) {
|
||||
$scope.element.html = html;
|
||||
$scope.element.htmlUnsafe = $sce.trustAsHtml(html);
|
||||
};
|
||||
|
||||
$scope.element.setHtml($scope.element.html);
|
||||
}
|
||||
],
|
||||
templateUrl: environment.templateUrl("Html"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
@ -150,6 +150,23 @@
|
||||
$scope.delete = function (element) {
|
||||
element.delete();
|
||||
}
|
||||
|
||||
if ($scope.element.hasEditor) {
|
||||
$scope.edit = function () {
|
||||
$scope.$root.editElement($scope.element).then(function (args) {
|
||||
$scope.$apply(function () {
|
||||
if (args.cancel)
|
||||
return;
|
||||
|
||||
$scope.element.data = args.element.data;
|
||||
$scope.element.applyElementEditorModel(args.elementEditorModel);
|
||||
|
||||
if (!!$scope.element.setHtml)
|
||||
$scope.element.setHtml(args.element.html);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
configureForContainer: function ($scope, $element) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
this.allowedChildTypes = allowedChildTypes;
|
||||
this.children = children;
|
||||
this.isContainer = true;
|
||||
this.containerTemplateStyles = {};
|
||||
|
||||
var self = this;
|
||||
|
||||
@ -139,6 +140,17 @@
|
||||
else if (!!this.parent)
|
||||
this.parent.pasteChild(child);
|
||||
}
|
||||
|
||||
this.getContainerTemplateStyles = function () {
|
||||
var styles = this.containerTemplateStyles || {};
|
||||
var css = "";
|
||||
|
||||
for (var property in styles) {
|
||||
css += property + ":" + styles[property] + ";";
|
||||
}
|
||||
|
||||
return css;
|
||||
}
|
||||
};
|
||||
|
||||
})(LayoutEditor || (LayoutEditor = {}));
|
@ -20,19 +20,12 @@
|
||||
this.htmlUnsafe = html;
|
||||
}
|
||||
|
||||
var baseToObject = this.toObject;
|
||||
this.toObject = function () {
|
||||
return {
|
||||
"type": "Content"
|
||||
};
|
||||
};
|
||||
|
||||
this.toObject = function () {
|
||||
var result = this.elementToObject();
|
||||
result.contentType = this.contentType;
|
||||
var result = baseToObject();
|
||||
result.contentTypeLabel = this.contentTypeLabel;
|
||||
result.contentTypeClass = this.contentTypeClass;
|
||||
result.html = this.html;
|
||||
result.hasEditor = hasEditor;
|
||||
return result;
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
if (!type)
|
||||
throw new Error("Parameter 'type' is required.");
|
||||
|
||||
var self = this;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.htmlId = htmlId;
|
||||
@ -13,6 +14,7 @@
|
||||
this.isTemplated = isTemplated;
|
||||
this.rule = rule;
|
||||
|
||||
this.templateStyles = {};
|
||||
this.editor = null;
|
||||
this.parent = null;
|
||||
this.setIsFocusedEventHandlers = [];
|
||||
@ -163,7 +165,9 @@
|
||||
htmlClass: this.htmlClass,
|
||||
htmlStyle: this.htmlStyle,
|
||||
isTemplated: this.isTemplated,
|
||||
rule: this.rule
|
||||
rule: this.rule,
|
||||
contentType: this.contentType,
|
||||
hasEditor: this.hasEditor
|
||||
};
|
||||
};
|
||||
|
||||
@ -171,6 +175,10 @@
|
||||
return {};
|
||||
};
|
||||
|
||||
this.toObject = function () {
|
||||
return self.elementToObject();
|
||||
};
|
||||
|
||||
this.copy = function (clipboardData) {
|
||||
var text = this.getInnerText();
|
||||
clipboardData.setData("text/plain", text);
|
||||
@ -191,6 +199,17 @@
|
||||
if (!!this.parent)
|
||||
this.parent.paste(clipboardData);
|
||||
};
|
||||
|
||||
this.getTemplateStyles = function () {
|
||||
var styles = this.templateStyles || {};
|
||||
var css = "";
|
||||
|
||||
for (var property in styles) {
|
||||
css += property + ":" + styles[property] + ";";
|
||||
}
|
||||
|
||||
return css;
|
||||
}
|
||||
};
|
||||
|
||||
})(LayoutEditor || (LayoutEditor = {}));
|
@ -1,70 +0,0 @@
|
||||
var LayoutEditor;
|
||||
(function ($, LayoutEditor) {
|
||||
|
||||
LayoutEditor.Html = function (data, htmlId, htmlClass, htmlStyle, isTemplated, contentType, contentTypeLabel, contentTypeClass, html, hasEditor, rule) {
|
||||
LayoutEditor.Element.call(this, "Html", data, htmlId, htmlClass, htmlStyle, isTemplated, rule);
|
||||
|
||||
this.contentType = contentType;
|
||||
this.contentTypeLabel = contentTypeLabel;
|
||||
this.contentTypeClass = contentTypeClass;
|
||||
this.html = html;
|
||||
this.hasEditor = hasEditor;
|
||||
this.isContainable = true;
|
||||
|
||||
this.getInnerText = function () {
|
||||
return $($.parseHTML("<div>" + this.html + "</div>")).text();
|
||||
};
|
||||
|
||||
// This function will be overwritten by the Content directive.
|
||||
this.setHtml = function (html) {
|
||||
this.html = html;
|
||||
this.htmlUnsafe = html;
|
||||
}
|
||||
|
||||
this.toObject = function () {
|
||||
return {
|
||||
"type": "Html"
|
||||
};
|
||||
};
|
||||
|
||||
this.toObject = function () {
|
||||
var result = this.elementToObject();
|
||||
result.contentType = this.contentType;
|
||||
result.contentTypeLabel = this.contentTypeLabel;
|
||||
result.contentTypeClass = this.contentTypeClass;
|
||||
result.html = this.html;
|
||||
result.hasEditor = hasEditor;
|
||||
return result;
|
||||
};
|
||||
|
||||
var getEditorObject = this.getEditorObject;
|
||||
this.getEditorObject = function () {
|
||||
var dto = getEditorObject();
|
||||
return $.extend(dto, {
|
||||
Content: this.html
|
||||
});
|
||||
}
|
||||
|
||||
this.setHtml(html);
|
||||
};
|
||||
|
||||
LayoutEditor.Html.from = function (value) {
|
||||
var result = new LayoutEditor.Html(
|
||||
value.data,
|
||||
value.htmlId,
|
||||
value.htmlClass,
|
||||
value.htmlStyle,
|
||||
value.isTemplated,
|
||||
value.contentType,
|
||||
value.contentTypeLabel,
|
||||
value.contentTypeClass,
|
||||
value.html,
|
||||
value.hasEditor,
|
||||
value.rule);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
LayoutEditor.registerFactory("Html", function(value) { return LayoutEditor.Html.from(value); });
|
||||
|
||||
})(jQuery, LayoutEditor || (LayoutEditor = {}));
|
@ -119,7 +119,6 @@
|
||||
<Content Include="Scripts\frame.js" />
|
||||
<Content Include="Scripts\jquery.browser.js" />
|
||||
<Content Include="Scripts\jquery.deserialize.js" />
|
||||
<Content Include="Assets\JavaScript\LayoutEditor\Directives\Html.js" />
|
||||
<Content Include="Assets\JavaScript\LayoutEditor\Directives\Editor.js" />
|
||||
<Content Include="Assets\JavaScript\LayoutEditor\Directives\Canvas.js" />
|
||||
<Content Include="Assets\JavaScript\LayoutEditor\Directives\Child.js" />
|
||||
@ -139,7 +138,6 @@
|
||||
<Content Include="Assets\JavaScript\Models\Container.js" />
|
||||
<Content Include="Assets\JavaScript\Models\Content.js" />
|
||||
<Content Include="Assets\JavaScript\Models\Element.js" />
|
||||
<Content Include="Assets\JavaScript\Models\Html.js" />
|
||||
<Content Include="Assets\JavaScript\Models\Grid.js" />
|
||||
<Content Include="Assets\JavaScript\Models\Helpers.js" />
|
||||
<Content Include="Assets\JavaScript\Models\Row.js" />
|
||||
@ -537,9 +535,6 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Elements\Shape.Design.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\LayoutEditor.Template.Html.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Elements\Projection.Design.cshtml" />
|
||||
</ItemGroup>
|
||||
|
@ -1,9 +1,9 @@
|
||||
(function ($) {
|
||||
var LayoutDesignerHost = function (element) {
|
||||
var LayoutDesignerHost = function (element, layoutEditor) {
|
||||
var self = this;
|
||||
this.element = element;
|
||||
this.element.data("layout-designer-host", this);
|
||||
this.editor = window.layoutEditor;
|
||||
this.editor = layoutEditor;
|
||||
this.settings = {
|
||||
antiForgeryToken: self.element.data("anti-forgery-token"),
|
||||
editorDialogTitleFormat: self.element.data("editor-dialog-title-format"),
|
||||
@ -124,20 +124,6 @@
|
||||
// Export types.
|
||||
window.Orchard = window.Orchard || {};
|
||||
window.Orchard.Layouts = window.Orchard.Layouts || {};
|
||||
window.Orchard.Layouts.LayoutEditorHost = window.Orchard.Layouts.LayoutEditorHost || {};
|
||||
window.Orchard.Layouts.LayoutDesignerHost = LayoutDesignerHost;
|
||||
|
||||
$(function () {
|
||||
window.layoutDesignerHost = new LayoutDesignerHost($(".layout-designer"));
|
||||
$(".layout-designer").each(function (e) {
|
||||
var designer = $(this);
|
||||
var dialog = designer.find(".layout-editor-help-dialog");
|
||||
designer.find(".layout-editor-help-link").click(function (e) {
|
||||
dialog.dialog({
|
||||
modal: true,
|
||||
width: 840
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -35,8 +35,13 @@ namespace Orchard.Layouts.Services {
|
||||
node["htmlId"] = element.HtmlId;
|
||||
node["htmlClass"] = element.HtmlClass;
|
||||
node["htmlStyle"] = element.HtmlStyle;
|
||||
node["isTemplated"] = element.IsTemplated;
|
||||
node["rule"] = element.Rule;
|
||||
node["isTemplated"] = element.IsTemplated;
|
||||
node["hasEditor"] = element.Descriptor.EnableEditorDialog;
|
||||
node["contentType"] = element.Descriptor.TypeName;
|
||||
node["contentTypeLabel"] = element.Descriptor.DisplayText.Text;
|
||||
node["contentTypeClass"] = element.DisplayText.Text.HtmlClassify();
|
||||
node["contentTypeDescription"] = element.Descriptor.Description.Text;
|
||||
}
|
||||
|
||||
protected virtual void ToElement(T element, JToken node) {
|
||||
@ -100,7 +105,7 @@ namespace Orchard.Layouts.Services {
|
||||
|
||||
public virtual string LayoutElementType { get { return "Content"; } }
|
||||
public virtual bool CanMap(Element element) {
|
||||
return !(element is Container);
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual Element ToElement(IElementManager elementManager, DescribeElementsContext describeContext, JToken node) {
|
||||
@ -134,34 +139,6 @@ namespace Orchard.Layouts.Services {
|
||||
}
|
||||
}
|
||||
|
||||
public class HtmlModelMap : ContentModelMap {
|
||||
public HtmlModelMap(IShapeDisplay shapeDisplay, IElementDisplay elementDisplay)
|
||||
: base(shapeDisplay, elementDisplay) {
|
||||
}
|
||||
|
||||
public override int Priority {
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public override string LayoutElementType {
|
||||
get { return "Html"; }
|
||||
}
|
||||
|
||||
public override bool CanMap(Element element) {
|
||||
return element is Html;
|
||||
}
|
||||
|
||||
public override Element ToElement(IElementManager elementManager, DescribeElementsContext describeContext, JToken node) {
|
||||
var html = (string)node["html"];
|
||||
var element = (Html)base.ToElement(elementManager, describeContext, node);
|
||||
|
||||
// To support inline editing, we need to update the element's content.
|
||||
element.Content = html;
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
public class RecycleBinModelMap : ILayoutModelMap {
|
||||
public int Priority { get { return 0; } }
|
||||
public string LayoutElementType { get { return "RecycleBin"; } }
|
||||
|
@ -38,8 +38,20 @@
|
||||
jQuery(function () {
|
||||
var editorConfig = JSON.parse(LayoutEditor.decode("@Html.Raw(Url.Encode(Model.ConfigurationData))"));
|
||||
var editorCanvasData = JSON.parse(LayoutEditor.decode("@Html.Raw(Url.Encode(Model.Data))"));
|
||||
var layoutEditor = window.layoutEditor = new LayoutEditor.Editor(editorConfig, editorCanvasData);
|
||||
|
||||
window.layoutEditor = new LayoutEditor.Editor(editorConfig, editorCanvasData);
|
||||
var host = new window.Orchard.Layouts.LayoutDesignerHost($(".layout-designer"), layoutEditor);
|
||||
$(".layout-designer").each(function (e) {
|
||||
var designer = $(this);
|
||||
var dialog = designer.find(".layout-editor-help-dialog");
|
||||
designer.find(".layout-editor-help-link").click(function (e) {
|
||||
dialog.dialog({
|
||||
modal: true,
|
||||
width: 840
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="layout-children clearfix" ng-model="element.children" ui-sortable="sortableOptions">
|
||||
<div class="layout-children clearfix" ng-model="element.children" ui-sortable="sortableOptions" style="{{element.getContainerTemplateStyles()}}">
|
||||
<div class="clearfix" ng-repeat="child in element.children" ng-class="getClasses(child)" ng-mouseenter="child.setIsActive(true)" ng-mouseleave="child.setIsActive(false)" ng-click="click(child, $event)" tabindex="{{$id}}">
|
||||
<orc-layout-child element="child" />
|
||||
</div>
|
||||
|
@ -7,5 +7,5 @@
|
||||
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} up (Ctrl+Up)")" ng-click="element.moveUp()" ng-class="{disabled: !element.canMoveUp()}"><i class="fa fa-chevron-up"></i></li>
|
||||
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} down (Ctrl+Down)")" ng-click="element.moveDown()" ng-class="{disabled: !element.canMoveDown()}"><i class="fa fa-chevron-down"></i></li>
|
||||
</ul>
|
||||
<div id="layout-content-markup-{{::$id}}" class="layout-content-markup" ng-bind-html="element.htmlUnsafe" data-templated="{{element.isTemplated}}"></div>
|
||||
<div id="layout-content-markup-{{::$id}}" class="layout-content-markup" ng-bind-html="element.htmlUnsafe" data-templated="{{element.isTemplated}}" style="{{element.getTemplateStyles()}}"></div>
|
||||
</div>
|
@ -1,11 +0,0 @@
|
||||
<div class="layout-element-wrapper">
|
||||
<ul class="layout-panel layout-panel-main">
|
||||
<li class="layout-panel-item layout-panel-label">{{::element.contentTypeLabel}}</li>
|
||||
<li class="layout-panel-item layout-panel-action layout-panel-action-edit" ng-show="{{element.hasEditor}}" title="Edit {{element.contentTypeLabel.toLowerCase()}} content (Enter)" ng-click="edit()"><i class="fa fa-code"></i></li>
|
||||
@Display(New.LayoutEditor_Template_Properties(ElementTypeName: "{{element.contentTypeLabel.toLowerCase()}}"))
|
||||
<li class="layout-panel-item layout-panel-action" title="@T("Delete {{element.contentTypeLabel.toLowerCase()}} (Del)")" ng-click="delete(element)" ng-class="{disabled: !element.canDelete()}"><i class="fa fa-remove"></i></li>
|
||||
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} up (Ctrl+Up)")" ng-click="element.moveUp()" ng-class="{disabled: !element.canMoveUp()}"><i class="fa fa-chevron-up"></i></li>
|
||||
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} down (Ctrl+Down)")" ng-click="element.moveDown()" ng-class="{disabled: !element.canMoveDown()}"><i class="fa fa-chevron-down"></i></li>
|
||||
</ul>
|
||||
<div id="layout-content-markup-{{::$id}}" class="layout-content-markup" ng-bind-html="element.htmlUnsafe" ng-blur="updateContent($event)" data-templated="{{element.isTemplated}}"></div>
|
||||
</div>
|
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
|
||||
namespace Orchard.ContentManagement.MetaData {
|
||||
public static class MediaMetaDataExtensions {
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy image part creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
public static ContentTypeDefinitionBuilder AsImage(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.AsMedia()
|
||||
.WithPart("ImagePart");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy vector image part creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
public static ContentTypeDefinitionBuilder AsVectorImage(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.AsMedia()
|
||||
.WithPart("VectorImagePart");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy audio part creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
public static ContentTypeDefinitionBuilder AsAudio(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.AsMedia()
|
||||
.WithPart("AudioPart");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This extension method can be used for video image part creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
public static ContentTypeDefinitionBuilder AsVideo(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.AsMedia()
|
||||
.WithPart("VideoPart");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy document part creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
public static ContentTypeDefinitionBuilder AsDocument(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.AsMedia()
|
||||
.WithPart("DocumentPart");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy media part creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
public static ContentTypeDefinitionBuilder AsMedia(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.WithSetting("Stereotype", "Media")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("MediaPart")
|
||||
.WithPart("TitlePart");
|
||||
}
|
||||
}
|
||||
}
|
@ -57,57 +57,37 @@ namespace Orchard.MediaLibrary {
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Image", td => td
|
||||
.DisplayedAs("Image")
|
||||
.WithSetting("Stereotype", "Media")
|
||||
.WithSetting("MediaFileNameEditorSettings.ShowFileNameEditor", "True")
|
||||
.AsImage()
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("MediaPart")
|
||||
.WithPart("ImagePart")
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("VectorImage", td => td
|
||||
.DisplayedAs("Vector Image")
|
||||
.WithSetting("Stereotype", "Media")
|
||||
.WithSetting("MediaFileNameEditorSettings.ShowFileNameEditor", "True")
|
||||
.AsVectorImage()
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("MediaPart")
|
||||
.WithPart("VectorImagePart")
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Video", td => td
|
||||
.DisplayedAs("Video")
|
||||
.WithSetting("Stereotype", "Media")
|
||||
.WithSetting("MediaFileNameEditorSettings.ShowFileNameEditor", "True")
|
||||
.AsVideo()
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("MediaPart")
|
||||
.WithPart("VideoPart")
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Audio", td => td
|
||||
.DisplayedAs("Audio")
|
||||
.WithSetting("Stereotype", "Media")
|
||||
.WithSetting("MediaFileNameEditorSettings.ShowFileNameEditor", "True")
|
||||
.AsAudio()
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("MediaPart")
|
||||
.WithPart("AudioPart")
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("Document", td => td
|
||||
.DisplayedAs("Document")
|
||||
.WithSetting("Stereotype", "Media")
|
||||
.WithSetting("MediaFileNameEditorSettings.ShowFileNameEditor", "True")
|
||||
.AsDocument()
|
||||
.WithPart("IdentityPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("MediaPart")
|
||||
.WithPart("DocumentPart")
|
||||
.WithPart("TitlePart")
|
||||
);
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("OEmbed", td => td
|
||||
|
@ -125,6 +125,7 @@
|
||||
<Content Include="Scripts\Web.config" />
|
||||
<Content Include="Styles\Web.config" />
|
||||
<Compile Include="Drivers\VectorImagePartDriver.cs" />
|
||||
<Compile Include="Extensions\MediaMetaDataExtensions.cs" />
|
||||
<Compile Include="Factories\VectorImageFactory.cs" />
|
||||
<Compile Include="Handlers\MediaLibrarySettingsPartHandler.cs" />
|
||||
<Compile Include="Models\MediaLibrarySettingsPart.cs" />
|
||||
|
@ -14,7 +14,7 @@
|
||||
var promptOnNavigate = element.data("prompt-on-navigate");
|
||||
var showSaveWarning = element.data("show-save-warning");
|
||||
var addButton = element.find(".button.add");
|
||||
var saveButton = $('.button.save');
|
||||
var saveButton = element.find('.button.save');
|
||||
var removeAllButton = element.find(".button.remove");
|
||||
var template =
|
||||
'<li><div data-id="{contentItemId}" class="media-library-picker-item"><div class="thumbnail">{thumbnail}<div class="overlay"><h3>{title}</h3></div></div></div><a href="#" data-id="{contentItemId}" class="media-library-picker-remove">' + removeText + '</a>' + pipe + '<a href="{editLink}?ReturnUrl=' + returnUrl + '">' + editText + '</a></li>';
|
||||
|
@ -54,7 +54,7 @@ namespace Orchard.Redis.Caching {
|
||||
}
|
||||
|
||||
public void Remove(string key) {
|
||||
Database.KeyDelete(key);
|
||||
Database.KeyDelete(GetLocalizedKey(key));
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
|
@ -11,10 +11,7 @@ namespace Orchard.Search {
|
||||
ContentDefinitionManager.AlterTypeDefinition("SearchForm",
|
||||
cfg => cfg
|
||||
.WithPart("SearchFormPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.AsWidgetWithIdentity()
|
||||
);
|
||||
|
||||
return 3;
|
||||
|
@ -130,6 +130,10 @@
|
||||
<Project>{73a7688a-5bd3-4f7e-adfa-ce36c5a10e3b}</Project>
|
||||
<Name>Orchard.MediaLibrary</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Widgets\Orchard.Widgets.csproj">
|
||||
<Project>{194d3ccc-1153-474d-8176-fde8d7d0d0bd}</Project>
|
||||
<Name>Orchard.Widgets</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Module.txt" />
|
||||
|
@ -47,9 +47,7 @@ namespace Orchard.Tags {
|
||||
"TagCloud",
|
||||
cfg => cfg
|
||||
.WithPart("TagCloudPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.AsWidget()
|
||||
);
|
||||
|
||||
return 1;
|
||||
|
@ -163,6 +163,10 @@
|
||||
<Project>{66FCCD76-2761-47E3-8D11-B45D0001DDAA}</Project>
|
||||
<Name>Orchard.Autoroute</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Widgets\Orchard.Widgets.csproj">
|
||||
<Project>{194d3ccc-1153-474d-8176-fde8d7d0d0bd}</Project>
|
||||
<Name>Orchard.Widgets</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Placement.info">
|
||||
|
@ -42,7 +42,9 @@
|
||||
}
|
||||
</ul>
|
||||
|
||||
@if (!Model.Terms.Any() && AuthorizedFor(Orchard.Taxonomies.Permissions.CreateTerm)) {
|
||||
@if (Model.TaxonomyId == 0) {
|
||||
<p>@T("Your haven't specified a taxonomy for {0}", Model.DisplayName)</p>
|
||||
}else if (!Model.Terms.Any() && AuthorizedFor(Orchard.Taxonomies.Permissions.CreateTerm)) {
|
||||
<div class="no-terms">
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName)
|
||||
<a href="@Url.Action("Index", "TermAdmin", new { taxonomyId = Model.TaxonomyId, area = "Orchard.Taxonomies" })">@T("Create some terms")</a>
|
||||
|
@ -53,7 +53,9 @@ namespace Orchard.Tokens.Implementation {
|
||||
var replacements = Evaluate(options.Predicate == null ? tokens : tokens.Where(options.Predicate), data);
|
||||
|
||||
return replacements.Aggregate(tokenset.Item1,
|
||||
(current, replacement) => current.Replace((hashMode ? "#{" : "{") + replacement.Key + "}", (options.Encoding ?? ReplaceOptions.NoEncode)(replacement.Key, replacement.Value)));
|
||||
(current, replacement) => replacement.Value == null ?
|
||||
current : current.Replace((hashMode ? "#{" : "{") + replacement.Key + "}",
|
||||
(options.Encoding ?? ReplaceOptions.NoEncode)(replacement.Key, replacement.Value)));
|
||||
}
|
||||
|
||||
private static Tuple<string, IEnumerable<string>> Parse(string text, bool hashMode) {
|
||||
@ -111,4 +113,4 @@ namespace Orchard.Tokens.Implementation {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
|
||||
namespace Orchard.ContentManagement.MetaData {
|
||||
public static class WidgetsMetaDataExtensions {
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy widget creation. Adds all necessary parts and settings to the part.
|
||||
/// </summary>
|
||||
/// <returns>The ContentTypeDefinitionBuilder object on which this method is called.</returns>
|
||||
public static ContentTypeDefinitionBuilder AsWidget(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithSetting("Stereotype", "Widget");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This extension method can be used for easy widget creation. Adds all necessary parts and settings to the part. And adds IdentityPart too.
|
||||
/// </summary>
|
||||
/// <returns>The ContentTypeDefinitionBuilder object on which this method is called.</returns>
|
||||
public static ContentTypeDefinitionBuilder AsWidgetWithIdentity(this ContentTypeDefinitionBuilder builder) {
|
||||
return builder
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("WidgetPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithSetting("Stereotype", "Widget");
|
||||
}
|
||||
}
|
||||
}
|
@ -36,11 +36,8 @@ namespace Orchard.Widgets {
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("HtmlWidget",
|
||||
cfg => cfg
|
||||
.WithPart("WidgetPart")
|
||||
.WithPart("BodyPart")
|
||||
.WithPart("CommonPart")
|
||||
.WithPart("IdentityPart")
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.AsWidgetWithIdentity()
|
||||
);
|
||||
|
||||
return 5;
|
||||
|
@ -96,6 +96,7 @@
|
||||
<Compile Include="Controllers\AdminController.cs" />
|
||||
<Compile Include="ControlWrapper.cs" />
|
||||
<Compile Include="Drivers\LayerPartDriver.cs" />
|
||||
<Compile Include="Extensions\WidgetsMetaDataExtensions.cs" />
|
||||
<Compile Include="Handlers\DisplayedContentItemHandler.cs" />
|
||||
<Compile Include="Handlers\LayerHintHandler.cs" />
|
||||
<Compile Include="Drivers\WidgetPartDriver.cs" />
|
||||
|
@ -42,7 +42,7 @@ namespace Orchard.Widgets.Services{
|
||||
// Once the Condition Engine is done:
|
||||
// Get Layers and filter by zone and rule
|
||||
// NOTE: .ForType("Layer") is faster than .Query<LayerPart, LayerPartRecord>()
|
||||
var activeLayers = _orchardServices.ContentManager.Query<LayerPart>().WithQueryHints(new QueryHints().ExpandParts<LayerPart>()).ForType("Layer").List();
|
||||
var activeLayers = _orchardServices.ContentManager.Query<LayerPart>().ForType("Layer").List();
|
||||
|
||||
var activeLayerIds = new List<int>();
|
||||
foreach (var activeLayer in activeLayers) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Web;
|
||||
using Autofac;
|
||||
using Orchard.Logging;
|
||||
@ -15,23 +16,22 @@ namespace Orchard.Environment {
|
||||
// a different symbolic key is used for each tenant.
|
||||
// this guarantees the correct accessor is being resolved.
|
||||
readonly object _workContextKey = new object();
|
||||
|
||||
[ThreadStatic]
|
||||
static ConcurrentDictionary<object, WorkContext> _threadStaticContexts;
|
||||
private readonly string _workContextSlot;
|
||||
|
||||
public WorkContextAccessor(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILifetimeScope lifetimeScope) {
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_lifetimeScope = lifetimeScope;
|
||||
_workContextSlot = "WorkContext." + Guid.NewGuid().ToString("n");
|
||||
}
|
||||
|
||||
public WorkContext GetContext(HttpContextBase httpContext) {
|
||||
if (!httpContext.IsBackgroundContext())
|
||||
return httpContext.Items[_workContextKey] as WorkContext;
|
||||
|
||||
WorkContext workContext;
|
||||
return EnsureThreadStaticContexts().TryGetValue(_workContextKey, out workContext) ? workContext : null;
|
||||
var context = CallContext.LogicalGetData(_workContextSlot) as ObjectHandle;
|
||||
return context != null ? context.Unwrap() as WorkContext : null;
|
||||
}
|
||||
|
||||
public WorkContext GetContext() {
|
||||
@ -39,8 +39,8 @@ namespace Orchard.Environment {
|
||||
if (!httpContext.IsBackgroundContext())
|
||||
return GetContext(httpContext);
|
||||
|
||||
WorkContext workContext;
|
||||
return EnsureThreadStaticContexts().TryGetValue(_workContextKey, out workContext) ? workContext : null;
|
||||
var context = CallContext.LogicalGetData(_workContextSlot) as ObjectHandle;
|
||||
return context != null ? context.Unwrap() as WorkContext : null;
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) {
|
||||
@ -57,7 +57,6 @@ namespace Orchard.Environment {
|
||||
_workContextKey);
|
||||
}
|
||||
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope() {
|
||||
var httpContext = _httpContextAccessor.Current();
|
||||
if (!httpContext.IsBackgroundContext())
|
||||
@ -68,18 +67,9 @@ namespace Orchard.Environment {
|
||||
var events = workLifetime.Resolve<IEnumerable<IWorkContextEvents>>();
|
||||
events.Invoke(e => e.Started(), NullLogger.Instance);
|
||||
|
||||
return new ThreadStaticScopeImplementation(
|
||||
events,
|
||||
workLifetime,
|
||||
EnsureThreadStaticContexts(),
|
||||
_workContextKey);
|
||||
return new CallContextScopeImplementation(events, workLifetime, _workContextSlot);
|
||||
}
|
||||
|
||||
static ConcurrentDictionary<object, WorkContext> EnsureThreadStaticContexts() {
|
||||
return _threadStaticContexts ?? (_threadStaticContexts = new ConcurrentDictionary<object, WorkContext>());
|
||||
}
|
||||
|
||||
|
||||
class HttpContextScopeImplementation : IWorkContextScope {
|
||||
readonly WorkContext _workContext;
|
||||
readonly Action _disposer;
|
||||
@ -113,19 +103,23 @@ namespace Orchard.Environment {
|
||||
}
|
||||
}
|
||||
|
||||
class ThreadStaticScopeImplementation : IWorkContextScope {
|
||||
class CallContextScopeImplementation : IWorkContextScope {
|
||||
readonly WorkContext _workContext;
|
||||
readonly Action _disposer;
|
||||
|
||||
public ThreadStaticScopeImplementation(IEnumerable<IWorkContextEvents> events, ILifetimeScope lifetimeScope, ConcurrentDictionary<object, WorkContext> contexts, object workContextKey) {
|
||||
public CallContextScopeImplementation(IEnumerable<IWorkContextEvents> events, ILifetimeScope lifetimeScope, string workContextSlot) {
|
||||
|
||||
CallContext.LogicalSetData(workContextSlot, null);
|
||||
|
||||
_workContext = lifetimeScope.Resolve<WorkContext>();
|
||||
contexts.AddOrUpdate(workContextKey, _workContext, (a, b) => _workContext);
|
||||
var httpContext = lifetimeScope.Resolve<HttpContextBase>();
|
||||
_workContext.HttpContext = httpContext;
|
||||
|
||||
CallContext.LogicalSetData(workContextSlot, new ObjectHandle(_workContext));
|
||||
|
||||
_disposer = () => {
|
||||
events.Invoke(e => e.Finished(), NullLogger.Instance);
|
||||
|
||||
WorkContext removedContext;
|
||||
contexts.TryRemove(workContextKey, out removedContext);
|
||||
CallContext.FreeNamedDataSlot(workContextSlot);
|
||||
lifetimeScope.Dispose();
|
||||
};
|
||||
}
|
||||
|
@ -78,5 +78,9 @@ namespace Orchard.Localization {
|
||||
return string.Equals(_localized, that._localized);
|
||||
}
|
||||
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the cross-AppDomain lease on this object
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -421,5 +421,9 @@ namespace Orchard.Logging {
|
||||
}
|
||||
}
|
||||
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the cross-AppDomain lease on this object
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Web;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.Mvc.Extensions {
|
||||
public static class HttpContextBaseExtensions {
|
||||
|
@ -1,13 +1,31 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Web;
|
||||
using Autofac;
|
||||
|
||||
namespace Orchard.Mvc {
|
||||
public class HttpContextAccessor : IHttpContextAccessor {
|
||||
readonly ILifetimeScope _lifetimeScope;
|
||||
private HttpContextBase _httpContext;
|
||||
private IWorkContextAccessor _wca;
|
||||
|
||||
public HttpContextAccessor(ILifetimeScope lifetimeScope) {
|
||||
_lifetimeScope = lifetimeScope;
|
||||
}
|
||||
|
||||
public HttpContextBase Current() {
|
||||
var httpContext = GetStaticProperty();
|
||||
return !IsBackgroundHttpContext(httpContext) ? new HttpContextWrapper(httpContext) : _httpContext;
|
||||
|
||||
if (!IsBackgroundHttpContext(httpContext))
|
||||
return new HttpContextWrapper(httpContext);
|
||||
|
||||
if (_httpContext != null)
|
||||
return _httpContext;
|
||||
|
||||
if (_wca == null && _lifetimeScope.IsRegistered<IWorkContextAccessor>())
|
||||
_wca = _lifetimeScope.Resolve<IWorkContextAccessor>();
|
||||
|
||||
var workContext = _wca != null ? _wca.GetContext(null) : null;
|
||||
return workContext != null ? workContext.HttpContext : null;
|
||||
}
|
||||
|
||||
public void Set(HttpContextBase httpContext) {
|
||||
@ -15,7 +33,7 @@ namespace Orchard.Mvc {
|
||||
}
|
||||
|
||||
private static bool IsBackgroundHttpContext(HttpContext httpContext) {
|
||||
return httpContext == null || httpContext.Items.Contains(BackgroundHttpContextFactory.IsBackgroundHttpContextKey);
|
||||
return httpContext == null || httpContext.Items.Contains(MvcModule.IsBackgroundHttpContextKey);
|
||||
}
|
||||
|
||||
private static HttpContext GetStaticProperty() {
|
||||
@ -36,4 +54,4 @@ namespace Orchard.Mvc {
|
||||
return httpContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,20 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Instrumentation;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Autofac;
|
||||
using Orchard.Mvc.Extensions;
|
||||
using Orchard.Mvc.Routes;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Mvc {
|
||||
public class MvcModule : Module {
|
||||
public const string IsBackgroundHttpContextKey = "IsBackgroundHttpContext";
|
||||
|
||||
protected override void Load(ContainerBuilder moduleBuilder) {
|
||||
moduleBuilder.RegisterType<ShellRoute>().InstancePerDependency();
|
||||
@ -24,29 +26,11 @@ namespace Orchard.Mvc {
|
||||
moduleBuilder.Register(UrlHelperFactory).As<UrlHelper>().InstancePerDependency();
|
||||
}
|
||||
|
||||
private static bool IsRequestValid() {
|
||||
if (HttpContext.Current == null)
|
||||
return false;
|
||||
|
||||
try {
|
||||
// The "Request" property throws at application startup on IIS integrated pipeline mode.
|
||||
var req = HttpContext.Current.Request;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static HttpContextBase HttpContextBaseFactory(IComponentContext context) {
|
||||
if (IsRequestValid()) {
|
||||
return new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
|
||||
var httpContext = context.Resolve<IHttpContextAccessor>().Current();
|
||||
if (httpContext != null)
|
||||
return httpContext;
|
||||
|
||||
var siteService = context.Resolve<ISiteService>();
|
||||
|
||||
@ -54,17 +38,18 @@ namespace Orchard.Mvc {
|
||||
// so that the RequestContext will have been established when the time comes to actually load the site settings,
|
||||
// which requires activating the Site content item, which in turn requires a UrlHelper, which in turn requires a RequestContext,
|
||||
// thus preventing a StackOverflowException.
|
||||
|
||||
var baseUrl = new Func<string>(() => siteService.GetSiteSettings().BaseUrl);
|
||||
var httpContextBase = new HttpContextPlaceholder(baseUrl);
|
||||
|
||||
context.Resolve<IWorkContextAccessor>().CreateWorkContextScope(httpContextBase);
|
||||
return httpContextBase;
|
||||
}
|
||||
|
||||
static RequestContext RequestContextFactory(IComponentContext context) {
|
||||
var httpContextAccessor = context.Resolve<IHttpContextAccessor>();
|
||||
var httpContext = httpContextAccessor.Current();
|
||||
if (httpContext != null) {
|
||||
|
||||
var httpContext = HttpContextBaseFactory(context);
|
||||
|
||||
if (!httpContext.IsBackgroundContext()) {
|
||||
|
||||
var mvcHandler = httpContext.Handler as MvcHandler;
|
||||
if (mvcHandler != null) {
|
||||
@ -77,8 +62,8 @@ namespace Orchard.Mvc {
|
||||
return hasRequestContext.RequestContext;
|
||||
}
|
||||
}
|
||||
else {
|
||||
httpContext = HttpContextBaseFactory(context);
|
||||
else if (httpContext is HttpContextPlaceholder) {
|
||||
return ((HttpContextPlaceholder)httpContext).RequestContext;
|
||||
}
|
||||
|
||||
return new RequestContext(httpContext, new RouteData());
|
||||
@ -91,7 +76,9 @@ namespace Orchard.Mvc {
|
||||
/// <summary>
|
||||
/// Standin context for background tasks.
|
||||
/// </summary>
|
||||
public class HttpContextPlaceholder : HttpContextBase {
|
||||
public class HttpContextPlaceholder : HttpContextBase, IDisposable {
|
||||
private HttpContext _httpContext;
|
||||
private HttpRequestPlaceholder _request;
|
||||
private readonly Lazy<string> _baseUrl;
|
||||
private readonly IDictionary _items = new Dictionary<object, object>();
|
||||
|
||||
@ -99,8 +86,54 @@ namespace Orchard.Mvc {
|
||||
_baseUrl = new Lazy<string>(baseUrl);
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
_httpContext = null;
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current = null;
|
||||
}
|
||||
|
||||
public override HttpRequestBase Request {
|
||||
get { return new HttpRequestPlaceholder(new Uri(_baseUrl.Value)); }
|
||||
|
||||
// Note: To fully resolve the baseUrl, some factories are needed (HttpContextBase, RequestContext...),
|
||||
// so, doing this in such a factory creates a circular dependency (see HttpContextBase factory comments).
|
||||
|
||||
// When rendering a view in a background task, an Html Helper can access HttpContext.Current directly,
|
||||
// so, here we create a fake HttpContext based on the baseUrl, and use it to update HttpContext.Current.
|
||||
// We cannot do this before in a factory (see note above), anyway, by doing this on each Request access,
|
||||
// we have a better chance to maintain the HttpContext.Current state even with some asynchronous code.
|
||||
|
||||
get {
|
||||
if (_httpContext == null) {
|
||||
var httpContext = new HttpContext(new HttpRequest("", _baseUrl.Value, ""), new HttpResponse(new StringWriter()));
|
||||
httpContext.Items[IsBackgroundHttpContextKey] = true;
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
|
||||
if (HttpContext.Current != _httpContext)
|
||||
HttpContext.Current = _httpContext;
|
||||
|
||||
if (_request == null) {
|
||||
_request = new HttpRequestPlaceholder(this, _baseUrl);
|
||||
}
|
||||
return _request;
|
||||
}
|
||||
}
|
||||
|
||||
internal RequestContext RequestContext {
|
||||
|
||||
// Uses the Request object but without creating an HttpContext which would need to resolve the baseUrl,
|
||||
// so, can be used by the RequestContext factory without creating a circular dependency (see note above).
|
||||
|
||||
get {
|
||||
if (_request == null) {
|
||||
_request = new HttpRequestPlaceholder(this, _baseUrl);
|
||||
}
|
||||
return _request.RequestContext;
|
||||
}
|
||||
}
|
||||
|
||||
public override HttpSessionStateBase Session {
|
||||
get { return new HttpSessionStatePlaceholder(); }
|
||||
}
|
||||
|
||||
public override IHttpHandler Handler { get; set; }
|
||||
@ -130,6 +163,14 @@ namespace Orchard.Mvc {
|
||||
}
|
||||
}
|
||||
|
||||
public class HttpSessionStatePlaceholder : HttpSessionStateBase {
|
||||
public override object this[string name] {
|
||||
get {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HttpResponsePlaceholder : HttpResponseBase {
|
||||
public override string ApplyAppPathModifier(string virtualPath) {
|
||||
return virtualPath;
|
||||
@ -146,10 +187,36 @@ namespace Orchard.Mvc {
|
||||
/// standin context for background tasks.
|
||||
/// </summary>
|
||||
public class HttpRequestPlaceholder : HttpRequestBase {
|
||||
private readonly Uri _uri;
|
||||
private HttpContextBase _httpContext;
|
||||
private RequestContext _requestContext;
|
||||
private readonly Lazy<string> _baseUrl;
|
||||
private readonly NameValueCollection _queryString = new NameValueCollection();
|
||||
private Uri _uri;
|
||||
|
||||
public HttpRequestPlaceholder(Uri uri) {
|
||||
_uri = uri;
|
||||
public HttpRequestPlaceholder(HttpContextBase httpContext, Lazy<string> baseUrl) {
|
||||
_httpContext = httpContext;
|
||||
_baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public override RequestContext RequestContext {
|
||||
get {
|
||||
if (_requestContext == null) {
|
||||
_requestContext = new RequestContext(_httpContext, new RouteData());
|
||||
}
|
||||
return _requestContext;
|
||||
}
|
||||
}
|
||||
|
||||
public override NameValueCollection QueryString {
|
||||
get {
|
||||
return _queryString;
|
||||
}
|
||||
}
|
||||
|
||||
public override string RawUrl {
|
||||
get {
|
||||
return Url.OriginalString;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -179,13 +246,16 @@ namespace Orchard.Mvc {
|
||||
|
||||
public override Uri Url {
|
||||
get {
|
||||
if (_uri == null) {
|
||||
_uri = new Uri(_baseUrl.Value);
|
||||
}
|
||||
return _uri;
|
||||
}
|
||||
}
|
||||
|
||||
public override NameValueCollection Headers {
|
||||
get {
|
||||
return new NameValueCollection { { "Host", _uri.Authority } };
|
||||
return new NameValueCollection { { "Host", Url.Authority } };
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,16 +279,16 @@ namespace Orchard.Mvc {
|
||||
|
||||
public override string ApplicationPath {
|
||||
get {
|
||||
return _uri.LocalPath;
|
||||
return Url.LocalPath;
|
||||
}
|
||||
}
|
||||
|
||||
public override NameValueCollection ServerVariables {
|
||||
get {
|
||||
return new NameValueCollection {
|
||||
{ "SERVER_PORT", _uri.Port.ToString(CultureInfo.InvariantCulture) },
|
||||
{ "HTTP_HOST", _uri.Authority.ToString(CultureInfo.InvariantCulture) },
|
||||
|
||||
{ "SERVER_PORT", Url.Port.ToString(CultureInfo.InvariantCulture) },
|
||||
{ "HTTP_HOST", Url.Authority.ToString(CultureInfo.InvariantCulture) },
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -279,4 +349,4 @@ namespace Orchard.Mvc {
|
||||
public override int ScriptTimeout { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Lifetime;
|
||||
using System.Security;
|
||||
using System.Web.Hosting;
|
||||
using Orchard.Parameters;
|
||||
@ -32,28 +34,46 @@ namespace Orchard.Host {
|
||||
|
||||
[SecurityCritical]
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the license
|
||||
// never expire the cross-AppDomain lease on this object
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void ExtendLifeTimeLeases(TextReader input, TextWriter output) {
|
||||
// Orchard objects passed as parameters into this AppDomain should derive from MarshalByRefObject and have
|
||||
// infinite lease timeouts by means of their InitializeLifetimeService overrides. For the input/output
|
||||
// stream objects we approximate that behavior by immediately renewing the lease for 30 days.
|
||||
ExtendLifeTimeLease(input);
|
||||
ExtendLifeTimeLease(output);
|
||||
}
|
||||
|
||||
private static void ExtendLifeTimeLease(MarshalByRefObject obj) {
|
||||
if (RemotingServices.IsObjectOutOfAppDomain(obj)) {
|
||||
var lease = (ILease)RemotingServices.GetLifetimeService(obj);
|
||||
lease.Renew(TimeSpan.FromDays(30));
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
void IRegisteredObject.Stop(bool immediate) {
|
||||
HostingEnvironment.UnregisterObject(this);
|
||||
}
|
||||
|
||||
public CommandReturnCodes StartSession(TextReader input, TextWriter output) {
|
||||
ExtendLifeTimeLeases(input, output);
|
||||
_agent = CreateAgent();
|
||||
return StartHost(_agent, input, output);
|
||||
}
|
||||
|
||||
public void StopSession(TextReader input, TextWriter output) {
|
||||
if (_agent != null) {
|
||||
ExtendLifeTimeLeases(input, output);
|
||||
StopHost(_agent, input, output);
|
||||
_agent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public CommandReturnCodes RunCommand(TextReader input, TextWriter output, Logger logger, OrchardParameters args) {
|
||||
ExtendLifeTimeLeases(input, output);
|
||||
var agent = CreateAgent();
|
||||
CommandReturnCodes result = (CommandReturnCodes)agent.GetType().GetMethod("RunSingleCommand").Invoke(agent, new object[] {
|
||||
input,
|
||||
@ -66,6 +86,7 @@ namespace Orchard.Host {
|
||||
}
|
||||
|
||||
public CommandReturnCodes RunCommandInSession(TextReader input, TextWriter output, Logger logger, OrchardParameters args) {
|
||||
ExtendLifeTimeLeases(input, output);
|
||||
CommandReturnCodes result = (CommandReturnCodes)_agent.GetType().GetMethod("RunCommand").Invoke(_agent, new object[] {
|
||||
input,
|
||||
output,
|
||||
@ -77,6 +98,7 @@ namespace Orchard.Host {
|
||||
}
|
||||
|
||||
public CommandReturnCodes RunCommands(TextReader input, TextWriter output, Logger logger, IEnumerable<ResponseLine> responseLines) {
|
||||
ExtendLifeTimeLeases(input, output);
|
||||
var agent = CreateAgent();
|
||||
|
||||
CommandReturnCodes result = StartHost(agent, input, output);
|
||||
|
@ -17,5 +17,10 @@ namespace Orchard {
|
||||
_output.WriteLine(format, args);
|
||||
}
|
||||
}
|
||||
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the cross-AppDomain lease on this object
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,10 @@ namespace Orchard {
|
||||
public IList<string> Arguments { get; set; }
|
||||
public IList<string> ResponseFiles { get; set; }
|
||||
public IDictionary<string, string> Switches { get; set; }
|
||||
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the cross-AppDomain lease on this object
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,11 @@ namespace Orchard.ResponseFiles {
|
||||
public string LineText { get; set; }
|
||||
public int LineNumber { get; set; }
|
||||
public string[] Args { get; set; }
|
||||
|
||||
public override object InitializeLifetimeService() {
|
||||
// never expire the cross-AppDomain lease on this object
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class ResponseFileReader {
|
||||
|
Loading…
Reference in New Issue
Block a user