mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-23 12:53:33 +08:00

When a ContentShape is returned from a ContentFieldDriver alternates are added automatically Patterns include: ShapeName ShapeName__FieldName ShapeName__PartName ShapeName__FieldName__PartName For content fields the part name is, essentially, always the same as the content type name Field drivers must add a ContentPart property to the shape they return, or only the field name will be a valid alternate Updated TextFieldDriver Fixed a bug where a dash after a dot in a file name was preventing proper harvesting --HG-- branch : dev extra : rebase_source : cae3d8cf544628b5f35cfc584ebbedf4d505c8ce
126 lines
6.6 KiB
C#
126 lines
6.6 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Web;
|
|
using System.Web.Mvc;
|
|
using System.Web.Mvc.Html;
|
|
using Orchard.Caching;
|
|
using Orchard.DisplayManagement.Implementation;
|
|
using Orchard.Environment.Descriptor.Models;
|
|
using Orchard.Environment.Extensions;
|
|
using Orchard.Environment.Extensions.Models;
|
|
using Orchard.FileSystems.VirtualPath;
|
|
using Orchard.Logging;
|
|
|
|
namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
|
public class ShapeTemplateBindingStrategy : IShapeTableProvider {
|
|
private readonly ShellDescriptor _shellDescriptor;
|
|
private readonly IExtensionManager _extensionManager;
|
|
private readonly ICacheManager _cacheManager;
|
|
private readonly IVirtualPathMonitor _virtualPathMonitor;
|
|
private readonly IVirtualPathProvider _virtualPathProvider;
|
|
private readonly IEnumerable<IShapeTemplateHarvester> _harvesters;
|
|
private readonly IEnumerable<IShapeTemplateViewEngine> _shapeTemplateViewEngines;
|
|
|
|
|
|
public ShapeTemplateBindingStrategy(
|
|
IEnumerable<IShapeTemplateHarvester> harvesters,
|
|
ShellDescriptor shellDescriptor,
|
|
IExtensionManager extensionManager,
|
|
ICacheManager cacheManager,
|
|
IVirtualPathMonitor virtualPathMonitor,
|
|
IVirtualPathProvider virtualPathProvider,
|
|
IEnumerable<IShapeTemplateViewEngine> shapeTemplateViewEngines) {
|
|
_harvesters = harvesters;
|
|
_shellDescriptor = shellDescriptor;
|
|
_extensionManager = extensionManager;
|
|
_cacheManager = cacheManager;
|
|
_virtualPathMonitor = virtualPathMonitor;
|
|
_virtualPathProvider = virtualPathProvider;
|
|
_shapeTemplateViewEngines = shapeTemplateViewEngines;
|
|
Logger = NullLogger.Instance;
|
|
}
|
|
|
|
public ILogger Logger { get; set; }
|
|
|
|
private static IEnumerable<ExtensionDescriptor> Once(IEnumerable<FeatureDescriptor> featureDescriptors) {
|
|
var once = new ConcurrentDictionary<string, object>();
|
|
return featureDescriptors.Select(fd => fd.Extension).Where(ed => once.TryAdd(ed.Id, null)).ToList();
|
|
}
|
|
|
|
public void Discover(ShapeTableBuilder builder) {
|
|
var harvesterInfos = _harvesters.Select(harvester => new { harvester, subPaths = harvester.SubPaths() });
|
|
|
|
var availableFeatures = _extensionManager.AvailableFeatures();
|
|
var activeFeatures = availableFeatures.Where(FeatureIsEnabled);
|
|
var activeExtensions = Once(activeFeatures);
|
|
|
|
var hits = activeExtensions.SelectMany(extensionDescriptor => {
|
|
var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => {
|
|
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
|
|
var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
|
|
var fileNames = _cacheManager.Get(virtualPath, ctx => {
|
|
ctx.Monitor(_virtualPathMonitor.WhenPathChanges(virtualPath));
|
|
return _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName);
|
|
});
|
|
return new { harvesterInfo.harvester, basePath, subPath, virtualPath, fileNames };
|
|
}));
|
|
|
|
var fileContexts = pathContexts.SelectMany(pathContext => _shapeTemplateViewEngines.SelectMany(ve => {
|
|
var fileNames = ve.DetectTemplateFileNames(pathContext.fileNames);
|
|
return fileNames.Select(
|
|
fileName => new {
|
|
fileName = Path.GetFileNameWithoutExtension(fileName),
|
|
fileVirtualPath = Path.Combine(pathContext.virtualPath, fileName).Replace(Path.DirectorySeparatorChar, '/'),
|
|
pathContext
|
|
});
|
|
}));
|
|
|
|
var shapeContexts = fileContexts.SelectMany(fileContext => {
|
|
var harvestShapeInfo = new HarvestShapeInfo {
|
|
SubPath = fileContext.pathContext.subPath,
|
|
FileName = fileContext.fileName,
|
|
TemplateVirtualPath = fileContext.fileVirtualPath
|
|
};
|
|
var harvestShapeHits = fileContext.pathContext.harvester.HarvestShape(harvestShapeInfo);
|
|
return harvestShapeHits.Select(harvestShapeHit => new { harvestShapeInfo, harvestShapeHit, fileContext });
|
|
});
|
|
|
|
return shapeContexts.Select(shapeContext => new { extensionDescriptor, shapeContext });
|
|
});
|
|
|
|
|
|
foreach (var iter in hits) {
|
|
// templates are always associated with the namesake feature of module or theme
|
|
var hit = iter;
|
|
var featureDescriptors = iter.extensionDescriptor.Features.Where(fd => fd.Id == hit.extensionDescriptor.Id);
|
|
foreach (var featureDescriptor in featureDescriptors) {
|
|
Logger.Debug("Binding {0} as shape [{1}] for feature {2}",
|
|
hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
|
|
iter.shapeContext.harvestShapeHit.ShapeType,
|
|
featureDescriptor.Id);
|
|
|
|
builder.Describe(iter.shapeContext.harvestShapeHit.ShapeType)
|
|
.From(new Feature { Descriptor = featureDescriptor })
|
|
.BoundAs(
|
|
hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
|
|
shapeDescriptor => displayContext => Render(shapeDescriptor, displayContext, hit.shapeContext.harvestShapeInfo, hit.shapeContext.harvestShapeHit));
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool FeatureIsEnabled(FeatureDescriptor fd) {
|
|
return (DefaultExtensionTypes.IsTheme(fd.Extension.ExtensionType) && (fd.Id == "TheAdmin" || fd.Id == "SafeMode")) ||
|
|
_shellDescriptor.Features.Any(sf => sf.Name == fd.Id);
|
|
}
|
|
|
|
private IHtmlString Render(ShapeDescriptor shapeDescriptor, DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo, HarvestShapeHit harvestShapeHit) {
|
|
var htmlHelper = new HtmlHelper(displayContext.ViewContext, displayContext.ViewDataContainer);
|
|
return htmlHelper.Partial(harvestShapeInfo.TemplateVirtualPath, displayContext.Value);
|
|
}
|
|
|
|
}
|
|
}
|