Merge branch '1.8.x' into 1.x

Conflicts:
	src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Orchard.Azure.MediaServices.csproj
	src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs
This commit is contained in:
Sebastien Ros
2014-08-13 11:24:02 -07:00
18 changed files with 211 additions and 84 deletions

View File

@@ -13,7 +13,7 @@
<levelMin value="WARN" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %logger - %message%newline" />
<conversionPattern value="%date [%thread] %logger - %P{Tenant} - %message%newline %P{Url}%newline" />
</layout>
</appender>

View File

@@ -51,11 +51,6 @@ namespace Orchard.Core.Common.Drivers {
}
protected override DriverResult Editor(CommonPart part, IUpdateModel updater, dynamic shapeHelper) {
var currentUser = _authenticationService.GetAuthenticatedUser();
if (!_authorizationService.TryCheckAccess(StandardPermissions.SiteOwner, currentUser, part)) {
return null;
}
var model = new ContainerEditorViewModel();
if (part.Container != null)
model.ContainerId = part.Container.ContentItem.Id;

View File

@@ -12,6 +12,10 @@ namespace Orchard.Core.Common.Handlers {
IContentManager contentManager) {
Filters.Add(StorageFilter.For(identityRepository));
OnInitializing<IdentityPart>(AssignIdentity);
OnIndexing<IdentityPart>((context, part) => {
context.DocumentIndex.Add("identifier", part.Identifier).Store();
});
}
protected void AssignIdentity(InitializingContentContext context, IdentityPart part) {

View File

@@ -26,8 +26,16 @@
<span class="hint">@T("Save the current item and leave the input empty to have it automatically generated using the pattern {0} e.g., {1}", defaultPattern.Name, defaultPattern.Description)</span>
}
else {
<span>@Url.MakeAbsolute("/")@urlPrefix</span>
<span class="hint">@T("Save the current item and the url will be generated using the pattern {0} e.g., {1}", defaultPattern.Name, defaultPattern.Description)</span>
var hintClass = string.Empty;
if (!string.IsNullOrEmpty(Model.CurrentUrl)) {
hintClass = "hint";
<span>@Url.MakeAbsolute("/")@urlPrefix@Model.CurrentUrl</span>
}
if (string.IsNullOrEmpty(Model.CurrentUrl)
|| (!string.IsNullOrEmpty(Model.CurrentUrl) && Model.Settings.AutomaticAdjustmentOnEdit)) {
<span class="@hintClass">@T("Save the current item and the url will be generated using the pattern {0} e.g., {1}", defaultPattern.Name, defaultPattern.Description)</span>
}
}
@if (!String.IsNullOrEmpty(Model.CurrentUrl)) {
<span>

View File

@@ -184,15 +184,15 @@
<Content Include="Scripts\lib\dash.all.js" />
<Content Include="Scripts\lib\dash.min.js" />
<Content Include="Scripts\lib\jquery.blockui.js" />
<Content Include="Scripts\cloudmedia-admin-job.ts" />
<Content Include="Scripts\cloudmedia-admin-common.ts" />
<Content Include="Scripts\cloudmedia-autorefresh.ts" />
<Content Include="Scripts\cloudmedia-edit-asset-video.ts" />
<Content Include="Scripts\cloudmedia-edit-asset.ts" />
<Content Include="Scripts\cloudmedia-edit-cloudvideopart-direct.ts" />
<Content Include="Scripts\cloudmedia-edit-cloudvideopart.ts" />
<Content Include="Scripts\cloudmedia-edit-cloudvideopart-proxied.ts" />
<Content Include="Scripts\cloudmedia-metadata-cloudvideopart.ts" />
<None Include="Scripts\cloudmedia-admin-job.ts" />
<None Include="Scripts\cloudmedia-admin-common.ts" />
<None Include="Scripts\cloudmedia-autorefresh.ts" />
<None Include="Scripts\cloudmedia-edit-asset-video.ts" />
<None Include="Scripts\cloudmedia-edit-asset.ts" />
<None Include="Scripts\cloudmedia-edit-cloudvideopart-direct.ts" />
<None Include="Scripts\cloudmedia-edit-cloudvideopart.ts" />
<None Include="Scripts\cloudmedia-edit-cloudvideopart-proxied.ts" />
<None Include="Scripts\cloudmedia-metadata-cloudvideopart.ts" />
<Content Include="Scripts\lib\jquery.fileupload-process.js" />
<Content Include="Scripts\lib\jquery.fileupload-validate.js" />
<Content Include="Scripts\lib\jquery.fileupload.js" />
@@ -290,9 +290,9 @@
<Content Include="Scripts\cloudmedia-videoplayer-injectors-smp.ts" />
<Content Include="Scripts\cloudmedia-videoplayer-injectors.ts" />
<Content Include="Scripts\cloudmedia-videoplayer-main.ts" />
<TypeScriptCompile Include="Scripts\typings\moment.d.ts" />
<TypeScriptCompile Include="Scripts\typings\underscore.d.ts" />
<TypeScriptCompile Include="Scripts\typings\uri.d.ts" />
<None Include="Scripts\typings\moment.d.ts" />
<None Include="Scripts\typings\underscore.d.ts" />
<None Include="Scripts\typings\uri.d.ts" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
@@ -446,9 +446,9 @@
<Content Include="Views\Parts\CloudVideo.SummaryAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="Scripts\typings\jquery.d.ts" />
<TypeScriptCompile Include="Scripts\typings\jqueryui.d.ts" />
<TypeScriptCompile Include="Scripts\typings\knockout.d.ts" />
<None Include="Scripts\typings\jquery.d.ts" />
<None Include="Scripts\typings\jqueryui.d.ts" />
<None Include="Scripts\typings\knockout.d.ts" />
<Content Include="Scripts\cloudmedia-admin-settings.ts" />
</ItemGroup>
<ItemGroup>
@@ -551,7 +551,7 @@
<Content Include="Content\Strobe Media Playback Notice.docx" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\lib\MPEG Dash Notice.docx" />
<None Include="Scripts\lib\MPEG Dash Notice.docx" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\cloudmedia-admin-common.js.map" />

View File

@@ -50,7 +50,7 @@ namespace Orchard.ContentPicker.Drivers {
}
protected override DriverResult Editor(ContentPart part, Fields.ContentPickerField field, IUpdateModel updater, dynamic shapeHelper) {
var model = new ContentPickerFieldViewModel();
var model = new ContentPickerFieldViewModel { SelectedIds = string.Join(",", field.Ids) };
updater.TryUpdateModel(model, GetPrefix(field, part), null, null);

View File

@@ -284,11 +284,14 @@ namespace Orchard.ContentTypes.Controllers {
if (typeViewModel == null)
return HttpNotFound();
var typePartNames = new HashSet<string>(typeViewModel.Parts.Select(tvm => tvm.PartDefinition.Name));
var viewModel = new AddPartsViewModel {
Type = typeViewModel,
PartSelections = _contentDefinitionService.GetParts(false/*metadataPartsOnly*/)
.Where(cpd => !typeViewModel.Parts.Any(p => p.PartDefinition.Name == cpd.Name) && cpd.Settings.GetModel<ContentPartSettings>().Attachable)
.Select(cpd => new PartSelectionViewModel { PartName = cpd.Name, PartDisplayName = cpd.DisplayName, PartDescription = cpd.Description})
.Where(cpd => !typePartNames.Contains(cpd.Name) && cpd.Settings.GetModel<ContentPartSettings>().Attachable)
.Select(cpd => new PartSelectionViewModel { PartName = cpd.Name, PartDisplayName = cpd.DisplayName, PartDescription = cpd.Description })
.ToList()
};
return View(viewModel);

View File

@@ -195,22 +195,30 @@ namespace Orchard.ContentTypes.Services {
}
public IEnumerable<EditPartViewModel> GetParts(bool metadataPartsOnly) {
var typeNames = GetTypes().Select(ctd => ctd.Name);
var typeNames = new HashSet<string>(GetTypes().Select(ctd => ctd.Name));
// user-defined parts
// except for those parts with the same name as a type (implicit type's part or a mistake)
var userContentParts = _contentDefinitionManager
.ListPartDefinitions()
var userContentParts = _contentDefinitionManager.ListPartDefinitions()
.Where(cpd => !typeNames.Contains(cpd.Name))
.Select(cpd => new EditPartViewModel(cpd));
.Select(cpd => new EditPartViewModel(cpd))
.ToDictionary(
k => k.Name,
v => v);
// code-defined parts
var codeDefinedParts = metadataPartsOnly ?
Enumerable.Empty<EditPartViewModel>() :
_contentPartDrivers.SelectMany(d => d.GetPartInfo().Where(cpd => !userContentParts.Any(m => m.Name == cpd.PartName)).Select(cpi => new EditPartViewModel { Name = cpi.PartName }));
var codeDefinedParts = metadataPartsOnly
? Enumerable.Empty<EditPartViewModel>()
: _contentPartDrivers
.SelectMany(d => d.GetPartInfo()
.Where(cpd => !userContentParts.ContainsKey(cpd.PartName))
.Select(cpi => new EditPartViewModel { Name = cpi.PartName, DisplayName = cpi.PartName }))
.ToList();
// Order by display name
return userContentParts.Union(codeDefinedParts).OrderBy(m => m.DisplayName);
return codeDefinedParts
.Union(userContentParts.Values)
.OrderBy(m => m.DisplayName);
}
public EditPartViewModel GetPart(string name) {

View File

@@ -9,7 +9,7 @@
Script.Require("ContentPicker").AtFoot();
Script.Require("jQueryUI_Sortable").AtFoot();
Script.Require("jQueryColorBox");
Script.Include("nprogress.js", "mprogress.min.js").AtFoot();
Script.Include("nprogress.js", "nprogress.min.js").AtFoot();
Script.Include("orchard-lists-admin.js", "orchard-lists-admin.min.js").AtFoot();
var containerId = ((int?)Model.ContainerId).GetValueOrDefault();

View File

@@ -21,6 +21,19 @@ namespace Orchard.MediaLibrary.Fields {
}
}
/// <summary>
/// Gets the MediaUrl property of the first Media, or null if none
/// </summary>
public string FirstMediaUrl {
get {
if (!MediaParts.Any()) {
return null;
}
return MediaParts.First().MediaUrl;
}
}
private string EncodeIds(ICollection<int> ids) {
if (ids == null || !ids.Any()) {
return string.Empty;

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Commands;
using Orchard.Environment.Descriptor.Models;
@@ -57,11 +58,11 @@ namespace Orchard.Modules.Commands {
[CommandName("feature enable")]
public void Enable(params string[] featureNames) {
Context.Output.WriteLine(T("Enabling features {0}", string.Join(",", featureNames)));
bool listAvailableFeatures = false;
List<string> featuresToEnable = new List<string>();
string[] availableFeatures = _featureManager.GetAvailableFeatures().Select(x => x.Id).ToArray();
var listAvailableFeatures = false;
var featuresToEnable = new List<string>();
var availableFeatures = _featureManager.GetAvailableFeatures().Select(x => x.Id).OrderBy(x => x).ToArray();
foreach (var featureName in featureNames) {
if (availableFeatures.Contains(featureName)) {
if (availableFeatures.Contains(featureName, StringComparer.OrdinalIgnoreCase)) {
featuresToEnable.Add(featureName);
}
else {

View File

@@ -92,7 +92,7 @@ namespace Orchard.Modules.Services {
/// <param name="force">Boolean parameter indicating if the feature should disable the features which depend on it if required or fail otherwise.</param>
public void DisableFeatures(IEnumerable<string> featureIds, bool force) {
foreach (string featureId in _featureManager.DisableFeatures(featureIds, force)) {
var featureName = _featureManager.GetAvailableFeatures().Where(f => f.Id == featureId).First().Name;
var featureName = _featureManager.GetAvailableFeatures().Single(f => f.Id.Equals(featureId, StringComparison.OrdinalIgnoreCase)).Name;
Services.Notifier.Information(T("{0} was disabled", featureName));
}
}

View File

@@ -143,9 +143,6 @@ namespace Orchard.Tags.Controllers {
}
public JsonResult FetchSimilarTags(string snippet) {
if (!Services.Authorizer.Authorize(Permissions.ManageTags, T("Not authorized to fetch tags")))
return Json(null);
return Json(
_tagService.GetTagsByNameSnippet(snippet).Select(tag => tag.TagName).ToList(),
JsonRequestBehavior.AllowGet

View File

@@ -66,20 +66,22 @@ namespace Orchard.Tokens.Providers {
return String.Empty;
}
var index = param.IndexOf(',');
int index = param.IndexOf(',');
int limit = index == -1 ? Int32.Parse(param) : Int32.Parse(param.Substring(0, index));
// no ellipsis
if (token.Length <= limit) {
// no limit
return token;
}
if (index == -1) {
var limit = Int32.Parse(param);
token = token.Substring(0, limit);
// no ellipsis
return token.Substring(0, limit);
}
else {
var limit = Int32.Parse(param.Substring(0, index));
// ellipsis
var ellipsis = param.Substring(index + 1);
token = token.Substring(0, limit) + ellipsis;
return token.Substring(0, limit) + ellipsis;
}
return token;
}
}

View File

@@ -38,7 +38,7 @@ namespace Orchard.Environment {
IExtensionLoaderCoordinator extensionLoaderCoordinator,
IExtensionMonitoringCoordinator extensionMonitoringCoordinator,
ICacheManager cacheManager,
IHostLocalRestart hostLocalRestart ) {
IHostLocalRestart hostLocalRestart) {
_shellSettingsManager = shellSettingsManager;
_shellContextFactory = shellContextFactory;
_runningShellTable = runningShellTable;
@@ -90,8 +90,10 @@ namespace Orchard.Environment {
MonitorExtensions();
BuildCurrent();
var shellContext = CreateShellContext(shellSettings);
return shellContext.LifetimeScope.CreateWorkContextScope();
var workContext = shellContext.LifetimeScope.CreateWorkContextScope();
return new StandaloneEnvironmentWorkContextScopeWrapper(workContext, shellContext);
}
/// <summary>
@@ -153,17 +155,17 @@ namespace Orchard.Environment {
/// Starts a Shell and registers its settings in RunningShellTable
/// </summary>
private void ActivateShell(ShellContext context) {
Logger.Debug("Activating context for tenant {0}", context.Settings.Name);
Logger.Debug("Activating context for tenant {0}", context.Settings.Name);
context.Shell.Activate();
_shellContexts = (_shellContexts ?? Enumerable.Empty<ShellContext>())
.Where(c => c.Settings.Name != context.Settings.Name)
.Concat(new[] { context })
.ToArray();
.ToArray();
_runningShellTable.Add(context.Settings);
}
/// <summary>
/// Creates a transient shell for the default tenant's setup
/// </summary>
@@ -214,7 +216,7 @@ namespace Orchard.Environment {
if (_shellContexts != null) {
foreach (var shellContext in _shellContexts) {
shellContext.Shell.Terminate();
shellContext.LifetimeScope.Dispose();
shellContext.Dispose();
}
}
}
@@ -275,7 +277,7 @@ namespace Orchard.Environment {
// terminate the shell if the tenant was disabled
else if (settings.State == TenantState.Disabled) {
shellContext.Shell.Terminate();
shellContext.LifetimeScope.Dispose();
shellContext.Dispose();
_runningShellTable.Remove(settings);
_shellContexts = _shellContexts.Where(shell => shell.Settings.Name != settings.Name);
@@ -284,7 +286,7 @@ namespace Orchard.Environment {
else {
// dispose previous context
shellContext.Shell.Terminate();
shellContext.LifetimeScope.Dispose();
shellContext.Dispose();
var context = _shellContextFactory.CreateShellContext(settings);
@@ -326,5 +328,33 @@ namespace Orchard.Environment {
Logger.Debug("Adding tenant to restart: " + tenant);
_tenantsToRestart.GetState().Add(context.Settings);
}
// To be used from CreateStandaloneEnvironment(), also disposes the ShellContext LifetimeScope.
private class StandaloneEnvironmentWorkContextScopeWrapper : IWorkContextScope {
private readonly ShellContext _shellContext;
private readonly IWorkContextScope _workContextScope;
public WorkContext WorkContext {
get { return _workContextScope.WorkContext; }
}
public StandaloneEnvironmentWorkContextScopeWrapper(IWorkContextScope workContextScope, ShellContext shellContext) {
_workContextScope = workContextScope;
_shellContext = shellContext;
}
public TService Resolve<TService>() {
return _workContextScope.Resolve<TService>();
}
public bool TryResolve<TService>(out TService service) {
return _workContextScope.TryResolve<TService>(out service);
}
public void Dispose() {
_workContextScope.Dispose();
_shellContext.Dispose();
}
}
}
}

View File

@@ -1,14 +1,42 @@
using System;
using Autofac;
using Orchard.Environment.Configuration;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Environment.ShellBuilders {
public class ShellContext {
public class ShellContext : IDisposable {
private bool _disposed = false;
public ShellSettings Settings { get; set; }
public ShellDescriptor Descriptor { get; set; }
public ShellBlueprint Blueprint { get; set; }
public ILifetimeScope LifetimeScope { get; set; }
public IOrchardShell Shell { get; set; }
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
LifetimeScope.Dispose();
}
Settings = null;
Descriptor = null;
Blueprint = null;
Shell = null;
_disposed = true;
}
}
~ShellContext() {
Dispose(false);
}
}
}

View File

@@ -105,34 +105,62 @@ namespace Orchard.Mvc.Html {
}
private static IHtmlString UnorderedList<T>(IEnumerable<T> items, Func<T, int, IHtmlString> generateContent, string cssClass, Func<T, string> generateItemCssClass, Func<T, string> generateAlternatingItemCssClass) {
if (items == null || !items.Any()) return new HtmlString(string.Empty);
if(items == null) {
return new HtmlString(string.Empty);
}
// prevent multiple evaluations of the enumeration
items = items.ToArray();
if (!items.Any()) {
return new HtmlString(string.Empty);
}
var sb = new StringBuilder(250);
int counter = 0, count = items.Count() - 1;
sb.AppendFormat(
!string.IsNullOrEmpty(cssClass) ? "<ul class=\"{0}\">" : "<ul>",
cssClass
);
if(string.IsNullOrEmpty(cssClass)) {
sb.Append("<ul>");
}
else {
sb.Append("<ul class=\"")
.Append(cssClass)
.Append("\">");
}
foreach (var item in items) {
var sbClass = new StringBuilder(50);
if (counter == 0)
if (counter == 0) {
sbClass.Append("first ");
if (counter == count)
sbClass.Append("last ");
if (generateItemCssClass != null)
sbClass.AppendFormat("{0} ", generateItemCssClass(item));
if (counter % 2 != 0 && generateAlternatingItemCssClass != null)
sbClass.AppendFormat("{0} ", generateAlternatingItemCssClass(item));
}
sb.AppendFormat(
sbClass.Length > 0
? string.Format("<li class=\"{0}\">{{0}}</li>", sbClass.ToString().TrimEnd())
: "<li>{0}</li>",
generateContent(item, counter)
);
if (counter == count) {
sbClass.Append("last ");
}
if (generateItemCssClass != null) {
sbClass.Append(generateItemCssClass(item)).Append(" ");
}
if (counter % 2 != 0 && generateAlternatingItemCssClass != null) {
sbClass.Append(generateAlternatingItemCssClass(item)).Append(" ");
}
var clss = sbClass.ToString().TrimEnd();
if(String.IsNullOrWhiteSpace(clss)) {
sb.Append("<li>")
.Append(generateContent(item, counter))
.Append("</li>");
}
else {
sb.Append("<li class=\"")
.Append(clss)
.Append("\">")
.Append(generateContent(item, counter))
.Append("</li>");
}
counter++;
}

View File

@@ -96,17 +96,27 @@ namespace MSBuild.Orchard.Tasks {
.Elements(None);
foreach (var element in elements) {
var include = (element.Attribute(Include) == null ? null : element.Attribute(Include).Value);
bool isValid = string.IsNullOrEmpty(include);
var filePath = (element.Attribute(Include) == null ? null : element.Attribute(Include).Value);
bool isValid = IsValidExcludeFile(filePath);
if (!isValid) {
string message = string.Format(
"\"{0}\" element name for include \"{1}\" should be \"{2}\".",
element.Name.LocalName, include, Content.LocalName);
element.Name.LocalName, filePath, Content.LocalName);
AddValidationError(element, message);
}
}
}
private static bool IsValidExcludeFile(string filePath) {
var validExtensions = new[] { ".sass", ".scss", ".less", ".coffee", ".ls", ".ts", ".md", ".docx" };
if (string.IsNullOrEmpty(filePath)) return true;
var fileExtension = Path.GetExtension(filePath);
if (string.IsNullOrEmpty(fileExtension)) return false;
return validExtensions.Contains(fileExtension, StringComparer.InvariantCultureIgnoreCase);
}
private void CheckCodeAnalysisRuleSet(XDocument document) {
const string orchardbasiccorrectnessRuleset = "OrchardBasicCorrectness.ruleset";