public void FeatureDescriptorsAreInDependencyOrder() { var extensionLoader = new StubLoaders(); var extensionFolder = new StubFolders(); extensionFolder.Manifests.Add("Alpha", @" Name: Alpha Version: 1.0.3 OrchardVersion: 1 Features: Alpha: Dependencies: Gamma "); extensionFolder.Manifests.Add("Beta", @" Name: Beta Version: 1.0.3 OrchardVersion: 1 "); extensionFolder.Manifests.Add("Gamma", @" Name: Gamma Version: 1.0.3 OrchardVersion: 1 Features: Gamma: Dependencies: Beta "); IExtensionManager extensionManager = CreateExtensionManager(extensionFolder, extensionLoader); var features = extensionManager.AvailableFeatures(); Assert.That(features.Aggregate("<", (a, b) => a + b.Id + "<"), Is.EqualTo("<Beta<Gamma<Alpha<")); }
private IEnumerable <string> GetFeatures() { var features = new[] { "Rabbit.Kernel" }.Concat( _extensionManager.AvailableFeatures().Select(i => i.Id)).ToArray(); return(features); }
private IEnumerable <string> GetFeatures() { var features = new[] { "SuperRocket.Framework" }.Concat( _extensionManager.AvailableFeatures().Select(i => i.Id)).ToArray(); return(features); }
public ShellBlueprint Compose(ShellSettings settings, ShellDescriptor descriptor) { Logger.Debug("Composing blueprint"); var builtinFeatures = BuiltinFeatures().ToList(); var builtinFeatureDescriptors = builtinFeatures.Select(x => x.Descriptor).ToList(); var availableFeatures = _extensionManager.AvailableFeatures() .Concat(builtinFeatureDescriptors) .GroupBy(x => x.Id.ToLowerInvariant()) // prevent duplicates .Select(x => x.FirstOrDefault()) .ToDictionary(x => x.Id, StringComparer.OrdinalIgnoreCase); var enabledFeatures = _extensionManager.EnabledFeatures(descriptor).Select(x => x.Id).ToList(); var expandedFeatures = ExpandDependencies(availableFeatures, descriptor.Features.Select(x => x.Name)).ToList(); var autoEnabledDependencyFeatures = expandedFeatures.Except(enabledFeatures).Except(builtinFeatureDescriptors.Select(x => x.Id)).ToList(); var featureDescriptors = _extensionManager.EnabledFeatures(expandedFeatures.Select(x => new ShellFeature { Name = x })).ToList(); var features = _extensionManager.LoadFeatures(featureDescriptors); if (descriptor.Features.Any(feature => feature.Name == "Boying.Framework")) { features = builtinFeatures.Concat(features); } var excludedTypes = GetExcludedTypes(features); var modules = BuildBlueprint(features, IsModule, BuildModule, excludedTypes); var dependencies = BuildBlueprint(features, IsDependency, (t, f) => BuildDependency(t, f, descriptor), excludedTypes); var controllers = BuildBlueprint(features, IsController, BuildController, excludedTypes); var httpControllers = BuildBlueprint(features, IsHttpController, BuildController, excludedTypes); var records = BuildBlueprint(features, IsRecord, (t, f) => BuildRecord(t, f, settings), excludedTypes); var result = new ShellBlueprint { Settings = settings, Descriptor = descriptor, Dependencies = dependencies.Concat(modules).ToArray(), Controllers = controllers, HttpControllers = httpControllers, Records = records, }; Logger.Debug("Done composing blueprint."); if (autoEnabledDependencyFeatures.Any()) { // Add any dependencies previously not enabled to the shell descriptor. descriptor.Features = descriptor.Features.Concat(autoEnabledDependencyFeatures.Select(x => new ShellFeature { Name = x })).ToList(); Logger.Information("Automatically enabled the following dependency features: {0}.", String.Join(", ", autoEnabledDependencyFeatures)); } return(result); }
public void Discover(ShapeTableBuilder builder) { var availableFeatures = _extensionManager.AvailableFeatures(); var activeFeatures = availableFeatures.Where(fd => FeatureIsTheme(fd) || FeatureIsEnabled(fd)); var activeExtensions = Once(activeFeatures); foreach (var featureDescriptor in activeExtensions.SelectMany(extensionDescriptor => extensionDescriptor.Descriptor.Features.Where(fd => fd.Id == fd.Extension.Id))) { ProcessFeatureDescriptor(builder, featureDescriptor); } }
void CreateAndActivateShells() { if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Start creation of shells"); } // Load all extensions and features so that the controllers are // registered in ITypeFeatureProvider and their areas definedin the application // conventions. _extensionManager.LoadFeatures(_extensionManager.AvailableFeatures()); // Is there any tenant right now? var allSettings = _shellSettingsManager.LoadSettings() .Where(settings => settings.State == TenantState.Running || settings.State == TenantState.Uninitialized || settings.State == TenantState.Initializing) .ToArray(); // Load all tenants, and activate their shell. if (allSettings.Any()) { Parallel.ForEach(allSettings, settings => { try { var context = CreateShellContext(settings); ActivateShell(context); } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(string.Format("A tenant could not be started: {0}", settings.Name), ex); } }); } // No settings, run the Setup. else { var setupContext = CreateSetupContext(); ActivateShell(setupContext); } if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Done creating shells"); } }
/// <summary> /// 获取开启的特性。 /// </summary> /// <param name="extensionManager">扩展管理者。</param> /// <param name="descriptor">外壳描述符。</param> /// <returns></returns> public static IEnumerable <FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) { extensionManager.NotNull("extensionManager"); var features = extensionManager.AvailableFeatures(); if (descriptor != null) { features = features.Where(fd => descriptor.Features.Any(sf => sf.Name == fd.Id)); } return(features.ToArray()); }
public ActionResult Index() { var availableFeatures = _extensionManager.AvailableFeatures().Select(i => i.Id).ToArray(); var currentFeatures = _shellDescriptor.Features.Select(i => i.Name).ToArray(); var model = availableFeatures.Select(i => new FeatureViewModel { Name = i, Enable = currentFeatures.Contains(i) }).ToArray(); return(View(model)); }
private IEnumerable <ExtensionDescriptor> GetBaseThemes(ExtensionDescriptor themeExtension) { if (themeExtension.Id.Equals("TheAdmin", StringComparison.OrdinalIgnoreCase)) { // Special case: conceptually, the base themes of "TheAdmin" is the list of all // enabled themes. This is so that any enabled theme can have controller/action/views // in the Admin of the site. return(_extensionManager .EnabledFeatures(_shellDescriptor) .Reverse() // reverse from (C <= B <= A) to (A => B => C) .Select(fd => fd.Extension) .Where(fd => DefaultExtensionTypes.IsTheme(fd.ExtensionType))); } else { var availableFeatures = _extensionManager.AvailableFeatures(); var list = new List <ExtensionDescriptor>(); while (true) { if (themeExtension == null) { break; } if (String.IsNullOrEmpty(themeExtension.BaseTheme)) { break; } var baseFeature = availableFeatures.FirstOrDefault(fd => fd.Id == themeExtension.BaseTheme); if (baseFeature == null) { Logger.Error("Base theme '{0}' of theme '{1}' not found in list of features", themeExtension.BaseTheme, themeExtension.Id); break; } // Protect against potential infinite loop if (list.Contains(baseFeature.Extension)) { Logger.Error("Base theme '{0}' of theme '{1}' ignored, as it seems there is recursion in base themes", themeExtension.BaseTheme, themeExtension.Id); break; } list.Add(baseFeature.Extension); themeExtension = baseFeature.Extension; } return(list); } }
public Task <ShellDescriptor> GetShellDescriptorAsync() { if (_shellDescriptor == null) { _shellDescriptor = new ShellDescriptor { Features = _extensionManager.AvailableFeatures().Select(x => new ShellFeature { Name = x.Id }).ToList() }; } return(Task.FromResult(_shellDescriptor)); }
public void Discover(ShapeTableBuilder builder) { var availableFeatures = _extensionManager.AvailableFeatures(); var activeFeatures = availableFeatures.Where(FeatureIsEnabled); var activeExtensions = Once(activeFeatures); var hits = activeExtensions.SelectMany(extensionDescriptor => { var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/'); var virtualPath = Path.Combine(basePath, GetFolder()).Replace(Path.DirectorySeparatorChar, '/'); var shapes = _virtualPathProvider.ListFiles(virtualPath) .Select(Path.GetFileName) .Where(fileName => string.Equals(Path.GetExtension(fileName), GetFileExtension(), StringComparison.OrdinalIgnoreCase)) .Select(cssFileName => new { fileName = Path.GetFileNameWithoutExtension(cssFileName), fileVirtualPath = Path.Combine(virtualPath, cssFileName).Replace(Path.DirectorySeparatorChar, '/'), shapeType = GetShapePrefix() + GetAlternateShapeNameFromFileName(cssFileName), extensionDescriptor }); return(shapes); }); foreach (var iter in hits) { var hit = iter; var featureDescriptors = hit.extensionDescriptor.Features.Where(fd => fd.Id == hit.extensionDescriptor.Id); foreach (var featureDescriptor in featureDescriptors) { builder.Describe(iter.shapeType) .From(new Feature { Descriptor = featureDescriptor }) .BoundAs( hit.fileVirtualPath, shapeDescriptor => displayContext => { var shape = ((dynamic)displayContext.Value); var output = displayContext.ViewContext.Writer; ResourceDefinition resource = shape.Resource; string condition = shape.Condition; Dictionary <string, string> attributes = shape.TagAttributes; ResourceManager.WriteResource(output, resource, hit.fileVirtualPath, condition, attributes); return(null); }); } } }
public IEnumerable <string> HarvestReactEnabledModules() { var availableFeatures = _extensionManager.AvailableFeatures(); var activeFeatures = availableFeatures.Where(FeatureIsEnabled); var activeExtensions = Once(activeFeatures).ToList(); var modulesWithReactCode = _parallelCacheContext.RunInParallel(activeExtensions, extensionDescriptor => { var containsReact = ReactFolderPaths().Select(folderPath => { var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/'); var virtualPath = Path.Combine(basePath, folderPath).Replace(Path.DirectorySeparatorChar, '/'); return(_virtualPathProvider.DirectoryExists(virtualPath) ? virtualPath : null); }).Where(x => x != null).ToList(); return(containsReact.Count > 0 ? containsReact.FirstOrDefault() : null); }).Where(x => x != null).ToList(); return(modulesWithReactCode); }
private IEnumerable <ExtensionDescriptorEntry> GetBaseThemes(ExtensionDescriptorEntry themeExtension) { //TODO:这边需要重新考虑 /*if (themeExtension.Id.Equals("TheAdmin", StringComparison.OrdinalIgnoreCase)) * { * return _extensionManager * .EnabledFeatures(_shellDescriptor) * .Reverse() * .Select(fd => fd.Extension) * .Where(fd => DefaultExtensionTypes.IsTheme(fd.ExtensionType)); * }*/ var availableFeatures = _extensionManager.AvailableFeatures().ToArray(); var list = new List <ExtensionDescriptorEntry>(); while (true) { if (themeExtension == null) { break; } if (String.IsNullOrEmpty(themeExtension.Descriptor.GetBaseTheme())) { break; } var baseFeature = availableFeatures.FirstOrDefault(fd => fd.Id == themeExtension.Descriptor.GetBaseTheme()); if (baseFeature == null) { Logger.Error("在 '{1}' 功能列表中找不到基础主题 '{0}'", themeExtension.Descriptor.GetBaseTheme(), themeExtension.Id); break; } //防止潜在的无限循环 if (list.Contains(baseFeature.Extension)) { Logger.Error("主题 '{1}' 是基础主题 '{0}' 所以被忽略", themeExtension.Descriptor.GetBaseTheme(), themeExtension.Id); break; } list.Add(baseFeature.Extension); themeExtension = baseFeature.Extension; } return(list); }
public void FeatureDescriptorsShouldBeLoadedInThemes() { var extensionLoader = new StubLoaders(); var moduleExtensionFolder = new StubFolders(); var themeExtensionFolder = new StubFolders(DefaultExtensionTypes.Theme); moduleExtensionFolder.Manifests.Add("Alpha", @" Name: Alpha Version: 1.0.3 SystemVersion: 1 Features: Alpha: Dependencies: Gamma "); moduleExtensionFolder.Manifests.Add("Beta", @" Name: Beta Version: 1.0.3 SystemVersion: 1 "); moduleExtensionFolder.Manifests.Add("Gamma", @" Name: Gamma Version: 1.0.3 SystemVersion: 1 Features: Gamma: Dependencies: Beta "); themeExtensionFolder.Manifests.Add("Classic", @" Name: Classic Version: 1.0.3 SystemVersion: 1 "); IExtensionManager extensionManager = CreateExtensionManager(new[] { moduleExtensionFolder, themeExtensionFolder }, new[] { extensionLoader }); var features = extensionManager.AvailableFeatures(); Assert.Equal(features.Count(), 4); }
private bool IsBaseTheme(string featureName, string themeName) { // determine if the given feature is a base theme of the given theme var availableFeatures = _extensionManager.AvailableFeatures(); var themeFeature = availableFeatures.SingleOrDefault(fd => fd.Id == themeName); while (themeFeature != null) { var baseTheme = themeFeature.Extension.BaseTheme; if (string.IsNullOrEmpty(baseTheme)) { return(false); } if (featureName == baseTheme) { return(true); } themeFeature = availableFeatures.SingleOrDefault(fd => fd.Id == baseTheme); } return(false); }
public void FeatureDescriptorsShouldBeLoadedInThemes() { var extensionLoader = new StubLoaders(); var moduleExtensionFolder = new StubExtensionLocator(new [] { DefaultExtensionTypes.Module, DefaultExtensionTypes.Theme }); moduleExtensionFolder.Manifests.Add("Alpha", @" Name: Alpha Version: 1.0.3 OrchardVersion: 1 Features: Alpha: Dependencies: Gamma "); moduleExtensionFolder.Manifests.Add("Beta", @" Name: Beta Version: 1.0.3 OrchardVersion: 1 "); moduleExtensionFolder.Manifests.Add("Gamma", @" Name: Gamma Version: 1.0.3 OrchardVersion: 1 Features: Gamma: Dependencies: Beta "); moduleExtensionFolder.ThemeManifests.Add("Classic", @" Name: Classic Version: 1.0.3 OrchardVersion: 1 "); IExtensionManager extensionManager = CreateExtensionManager(moduleExtensionFolder, new[] { extensionLoader }); var features = extensionManager.AvailableFeatures(); Assert.Equal(4, features.Count()); }
private bool IsBaseTheme(string featureName, string themeName) { //判断给定的功能是给定主题的基本主题 var availableFeatures = _extensionManager.AvailableFeatures().ToArray(); var themeFeature = availableFeatures.SingleOrDefault(fd => fd.Id == themeName); while (themeFeature != null) { var baseTheme = themeFeature.Extension.Descriptor.GetBaseTheme(); if (String.IsNullOrEmpty(baseTheme)) { return(false); } if (featureName == baseTheme) { return(true); } themeFeature = availableFeatures.SingleOrDefault(fd => fd.Id == baseTheme); } return(false); }
public void Discover(ShapeTableBuilder builder) { if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Start discovering shapes"); } 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.Select(extensionDescriptor => { if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Start discovering candidate views filenames"); } 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, '/'); IReadOnlyList <string> fileNames; if (!_virtualPathProvider.DirectoryExists(virtualPath)) { fileNames = new List <string>(); } else { fileNames = _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName).ToReadOnlyCollection(); } return(new { harvesterInfo.harvester, basePath, subPath, virtualPath, fileNames }); })).ToList(); if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Done discovering candidate views 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 }).ToList()); }).SelectMany(hits2 => hits2); 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) { if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug("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 => RenderAsync(shapeDescriptor, displayContext, hit.shapeContext.harvestShapeInfo, hit.shapeContext.harvestShapeHit)); } } if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Done discovering shapes"); } }
public static IEnumerable <FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) { return(extensionManager.AvailableFeatures()); }
public void Update(string feature) { if (_processedFeatures.Contains(feature)) { return; } _processedFeatures.Add(feature); Logger.Information("Updating feature: {0}", feature); // proceed with dependent features first, whatever the module it's in var dependencies = _extensionManager.AvailableFeatures() .Where(f => String.Equals(f.Id, feature, StringComparison.OrdinalIgnoreCase)) .Where(f => f.Dependencies != null) .SelectMany(f => f.Dependencies) .ToList(); foreach (var dependency in dependencies) { Update(dependency); } var migrations = GetDataMigrations(feature); // apply update methods to each migration class for the module foreach (var migration in migrations) { // copy the object for the Linq query var tempMigration = migration; // get current version for this migration var dataMigrationRecord = GetDataMigrationRecord(tempMigration); var current = 0; if (dataMigrationRecord != null) { current = dataMigrationRecord.Version.Value; } try { _transactionManager.RequireNew(); // do we need to call Create() ? if (current == 0) { // try to resolve a Create method var createMethod = GetCreateMethod(migration); if (createMethod != null) { current = (int)createMethod.Invoke(migration, new object[0]); } } var lookupTable = CreateUpgradeLookupTable(migration); while (lookupTable.ContainsKey(current)) { try { Logger.Information("Applying migration for {0} from version {1}", feature, current); current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}", feature, current); throw; } } // if current is 0, it means no upgrade/create method was found or succeeded if (current == 0) { continue; } if (dataMigrationRecord == null) { _dataMigrationRepository.Create(new DataMigrationRecord { Version = current, DataMigrationClass = migration.GetType().FullName }); } else { dataMigrationRecord.Version = current; } } catch (Exception e) { Logger.Error(e, "Error while running migration version {0} for {1}", current, feature); _transactionManager.Cancel(); } } }
public ActionResult Features() { if (!CheckPermission(DashboardPermissions.ManageModules)) { return(new HttpUnauthorizedResult()); } WorkContext.Breadcrumbs.Add(T("Modules")); WorkContext.Breadcrumbs.Add(T("Features")); var features = extensionManager.AvailableFeatures().Where(x => !DefaultExtensionTypes.IsTheme(x.Extension.ExtensionType)).ToList(); var groups = features.GroupBy(x => x.Category).OrderBy(x => x.Key); var htmlHelper = new HtmlHelper(new ViewContext(), new ViewDataContainer(ViewData)); var sb = new StringBuilder(); foreach (var @group in groups) { sb.AppendFormat("<h3>{0}</h3>", string.IsNullOrEmpty(group.Key) ? "Uncategorized" : group.Key); foreach (var descriptor in group.OrderBy(x => x.Name)) { if (descriptor.Name.Equals("CMS") || descriptor.Name.Equals("Security")) { continue; } var missingDependencies = descriptor.Dependencies.Where(d => !features.Any(f => f.Id.Equals(d, StringComparison.OrdinalIgnoreCase))).ToList(); var showDisable = @group.Key != "Core"; var showEnable = !missingDependencies.Any(); var enabled = shellDescriptor.Features.Any(x => x.Name == descriptor.Id); sb.AppendFormat("<div class=\"{1}\"><div class=\"well well-small feature\" id=\"{0}-feature\">", descriptor.Id.Replace(".", "-").ToSlugUrl(), Constants.ContainerCssClassCol3); sb.AppendFormat("<h4>{0}</h4>", descriptor.Name); sb.Append("<div class=\"actions\">"); if (showDisable && enabled) { sb.AppendFormat("<form action=\"{0}\" method=\"post\">", Url.Action("Disable")); sb.AppendFormat("<input type=\"hidden\" name=\"id\" value=\"{0}\" />", descriptor.Id); sb.Append(htmlHelper.AntiForgeryToken()); sb.AppendFormat("<button type=\"submit\" class=\"btn btn-link btn-disable-feature\">{0}</button>", T("Disable")); sb.Append("</form>"); } if (showEnable && !enabled) { sb.AppendFormat("<form action=\"{0}\" method=\"post\">", Url.Action("Enable")); sb.AppendFormat("<input type=\"hidden\" name=\"id\" value=\"{0}\" />", descriptor.Id); sb.Append(htmlHelper.AntiForgeryToken()); sb.AppendFormat("<button type=\"submit\" class=\"btn btn-link btn-enable-feature\">{0}</button>", T("Enable")); sb.Append("</form>"); } sb.Append("</div>"); var dependencies = (from d in descriptor.Dependencies select(from f in features where f.Id.Equals(d, StringComparison.OrdinalIgnoreCase) select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Name); if (!dependencies.IsNullOrEmpty()) { sb.Append("<div class=\"dependencies\">"); sb.AppendFormat("<strong>{0}:</strong>", T("Depends on")); sb.Append("<ul class=\"list-unstyled inline\">"); foreach (var dependency in dependencies) { sb.AppendFormat("<li><a href=\"#{1}-feature\">{0}</a></li>", dependency.Name, dependency.Id.Replace(".", "-").ToSlugUrl()); } sb.Append("</ul>"); sb.Append("</div>"); } if (!missingDependencies.IsNullOrEmpty()) { sb.Append("<div class=\"missing-dependencies\">"); sb.AppendFormat("<strong>{0}:</strong>", T("Missing")); sb.Append("<ul class=\"list-unstyled inline\">"); foreach (var dependency in missingDependencies) { sb.AppendFormat("<li>{0}</li>", dependency); } sb.Append("</ul>"); sb.Append("</div>"); } sb.Append("</div></div>"); } sb.Append("<div class='clearfix'></div>"); } return(new ControlContentResult(sb.ToString()) { Title = T("Modules") }); }
/// <summary> /// Retrieves the available features. /// </summary> /// <returns>An enumeration of feature descriptors for the available features.</returns> public IEnumerable <FeatureDescriptor> GetAvailableFeatures() { return(_extensionManager.AvailableFeatures()); }
/// <summary> /// Retrieves the available features. /// </summary> /// <returns>An enumeration of feature descriptors for the available features.</returns> public Task <IEnumerable <FeatureDescriptor> > GetAvailableFeaturesAsync() { return(Task.FromResult(_extensionManager.AvailableFeatures())); }
public static IEnumerable <FeatureDescriptor> DisabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) { return(extensionManager.AvailableFeatures().Where(fd => descriptor.Features.All(sf => sf.Name != fd.Id))); }
public static IEnumerable <FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, IEnumerable <ShellFeature> features) { return(extensionManager.AvailableFeatures().Where(fd => features.Any(sf => sf.Name == fd.Id))); }
void IShellStateManagerEventHandler.ApplyChanges() { Logger.Information("Applying changes for for shell '{0}'", _settings.Name); var shellState = _stateManager.GetShellState(); // start with description of all declared features in order - order preserved with all merging var orderedFeatureDescriptors = _extensionManager.AvailableFeatures(); // merge feature state into ordered list var orderedFeatureDescriptorsAndStates = orderedFeatureDescriptors .Select(featureDescriptor => new { FeatureDescriptor = featureDescriptor, FeatureState = shellState.Features.FirstOrDefault(s => s.Name == featureDescriptor.Id), }) .Where(entry => entry.FeatureState != null) .ToArray(); // get loaded feature information var loadedFeatures = _extensionManager.LoadFeatures(orderedFeatureDescriptorsAndStates.Select(entry => entry.FeatureDescriptor)).ToArray(); // merge loaded feature information into ordered list var loadedEntries = orderedFeatureDescriptorsAndStates.Select( entry => new { Feature = loadedFeatures.SingleOrDefault(f => f.Descriptor == entry.FeatureDescriptor) ?? new Feature { Descriptor = entry.FeatureDescriptor, ExportedTypes = Enumerable.Empty <Type>() }, entry.FeatureDescriptor, entry.FeatureState, }).ToList(); // find feature state that is beyond what's currently available from modules var additionalState = shellState.Features.Except(loadedEntries.Select(entry => entry.FeatureState)); // create additional stub entries for the sake of firing state change events on missing features var allEntries = loadedEntries.Concat(additionalState.Select(featureState => { var featureDescriptor = new FeatureDescriptor { Id = featureState.Name, Extension = new ExtensionDescriptor { Id = featureState.Name } }; return(new { Feature = new Feature { Descriptor = featureDescriptor, ExportedTypes = Enumerable.Empty <Type>(), }, FeatureDescriptor = featureDescriptor, FeatureState = featureState }); })).ToArray(); // lower enabled states in reverse order foreach (var entry in allEntries.Reverse().Where(entry => entry.FeatureState.EnableState == ShellFeatureState.State.Falling)) { Logger.Information("Disabling feature '{0}'", entry.Feature.Descriptor.Id); _featureEvents.Disabling(entry.Feature); _stateManager.UpdateEnabledState(entry.FeatureState, ShellFeatureState.State.Down); _featureEvents.Disabled(entry.Feature); } // lower installed states in reverse order foreach (var entry in allEntries.Reverse().Where(entry => entry.FeatureState.InstallState == ShellFeatureState.State.Falling)) { Logger.Information("Uninstalling feature '{0}'", entry.Feature.Descriptor.Id); _featureEvents.Uninstalling(entry.Feature); _stateManager.UpdateInstalledState(entry.FeatureState, ShellFeatureState.State.Down); _featureEvents.Uninstalled(entry.Feature); } // raise install and enabled states in order foreach (var entry in allEntries.Where(entry => IsRising(entry.FeatureState))) { if (entry.FeatureState.InstallState == ShellFeatureState.State.Rising) { Logger.Information("Installing feature '{0}'", entry.Feature.Descriptor.Id); _featureEvents.Installing(entry.Feature); _stateManager.UpdateInstalledState(entry.FeatureState, ShellFeatureState.State.Up); _featureEvents.Installed(entry.Feature); } if (entry.FeatureState.EnableState == ShellFeatureState.State.Rising) { Logger.Information("Enabling feature '{0}'", entry.Feature.Descriptor.Id); _featureEvents.Enabling(entry.Feature); _stateManager.UpdateEnabledState(entry.FeatureState, ShellFeatureState.State.Up); _featureEvents.Enabled(entry.Feature); } } // re-fire if any event handlers initiated additional state changes FireApplyChangesIfNeeded(); }
// public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) { // return EnabledFeatures(extensionManager, descriptor.Features); // } // // public static IEnumerable<FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, IEnumerable<ShellFeature> features) { // return extensionManager.AvailableFeatures().Where(fd => features.Any(sf => sf.Name == fd.Id)); // } // // public static IEnumerable<FeatureDescriptor> DisabledFeatures(this IExtensionManager extensionManager, ShellDescriptor descriptor) { // return extensionManager.AvailableFeatures().Where(fd => descriptor.Features.All(sf => sf.Name != fd.Id)); // } public static IEnumerable <FeatureDescriptor> EnabledFeatures(this IExtensionManager extensionManager, string shellName) { return(extensionManager.AvailableFeatures().Where(fd => shellName == fd.Name)); }
public async Task UpdateAsync(string feature) { if (_processedFeatures.Contains(feature)) { return; } _processedFeatures.Add(feature); if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Updating feature: {0}", feature); } // proceed with dependent features first, whatever the module it's in var dependencies = _extensionManager.AvailableFeatures() .Where(f => String.Equals(f.Id, feature, StringComparison.OrdinalIgnoreCase)) .Where(f => f.Dependencies != null) .SelectMany(f => f.Dependencies) .ToList(); foreach (var dependency in dependencies) { await UpdateAsync(dependency); } var migrations = GetDataMigrations(feature); // apply update methods to each migration class for the module foreach (var migration in migrations) { _session.ExecuteMigration(schemaBuilder => { migration.SchemaBuilder = schemaBuilder; // copy the object for the Linq query var tempMigration = migration; // get current version for this migration var dataMigrationRecord = GetDataMigrationRecordAsync(tempMigration).Result; var current = 0; if (dataMigrationRecord != null) { current = dataMigrationRecord.Version.Value; } else { dataMigrationRecord = new DataMigration { DataMigrationClass = migration.GetType().FullName }; _dataMigrationRecord.DataMigrations.Add(dataMigrationRecord); } try { // do we need to call Create() ? if (current == 0) { // try to resolve a Create method var createMethod = GetCreateMethod(migration); if (createMethod != null) { current = (int)createMethod.Invoke(migration, new object[0]); } } var lookupTable = CreateUpgradeLookupTable(migration); while (lookupTable.ContainsKey(current)) { try { if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Applying migration for {0} from version {1}.", feature, current); } current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(0, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current); throw; } } // if current is 0, it means no upgrade/create method was found or succeeded if (current == 0) { return; } dataMigrationRecord.Version = current; } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(0, "Error while running migration version {0} for {1}.", current, feature); _session.Cancel(); throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), ex); } finally { // Persist data migrations _session.Save(_dataMigrationRecord); } }); } }
/// <summary> /// Generates SchemaCommand instances in order to create the schema for a specific feature /// </summary> public IEnumerable <SchemaCommand> GetCreateFeatureCommands(string feature, bool drop) { var dependencies = _extensionManager.AvailableFeatures() .Where(f => String.Equals(f.Id, feature, StringComparison.OrdinalIgnoreCase)) .Where(f => f.Dependencies != null) .SelectMany(f => f.Dependencies) .ToList(); var shellDescriptor = new ShellDescriptor { Features = dependencies.Select(id => new ShellFeature { Name = id }).Union(new[] { new ShellFeature { Name = feature }, new ShellFeature { Name = "Orchard.Framework" } }) }; var shellBlueprint = _compositionStrategy.Compose(_shellSettings, shellDescriptor); if (!shellBlueprint.Records.Any()) { yield break; } //var features = dependencies.Select(name => new ShellFeature {Name = name}).Union(new[] {new ShellFeature {Name = feature}, new ShellFeature {Name = "Orchard.Framework"}}); var parameters = _sessionFactoryHolder.GetSessionFactoryParameters(); parameters.RecordDescriptors = shellBlueprint.Records; var configuration = _dataServicesProviderFactory .CreateProvider(parameters) .BuildConfiguration(parameters); Dialect.GetDialect(configuration.Properties); var mapping = configuration.BuildMapping(); // get the table mappings using reflection var tablesField = typeof(Configuration).GetField("tables", BindingFlags.Instance | BindingFlags.NonPublic); var tables = ((IDictionary <string, Table>)tablesField.GetValue(configuration)).Values; string prefix = feature.Replace(".", "_") + "_"; foreach (var table in tables.Where(t => parameters.RecordDescriptors.Any(rd => rd.Feature.Descriptor.Id == feature && rd.TableName == t.Name))) { string tableName = table.Name; var recordType = parameters.RecordDescriptors.First(rd => rd.Feature.Descriptor.Id == feature && rd.TableName == tableName).Type; var isContentPart = typeof(ContentPartRecord).IsAssignableFrom(recordType); if (tableName.StartsWith(prefix)) { tableName = tableName.Substring(prefix.Length); } if (drop) { yield return(new DropTableCommand(tableName)); } var command = new CreateTableCommand(tableName); foreach (var column in table.ColumnIterator) { // create copies for local variables to be evaluated at the time the loop is called, and not lately when the la;bda is executed var tableCopy = table; var columnCopy = column; var sqlType = columnCopy.GetSqlTypeCode(mapping); command.Column(column.Name, sqlType.DbType, action => { if (tableCopy.PrimaryKey.Columns.Any(c => c.Name == columnCopy.Name)) { action.PrimaryKey(); if (!isContentPart) { action.Identity(); } } if (columnCopy.IsLengthDefined() && new[] { DbType.StringFixedLength, DbType.String, DbType.AnsiString, DbType.AnsiStringFixedLength }.Contains(sqlType.DbType) && columnCopy.Length != Column.DefaultLength) { action.WithLength(columnCopy.Length); } if (columnCopy.IsPrecisionDefined()) { action.WithPrecision((byte)columnCopy.Precision); action.WithScale((byte)columnCopy.Scale); } if (columnCopy.IsNullable) { action.Nullable(); } if (columnCopy.IsUnique) { action.Unique(); } if (columnCopy.DefaultValue != null) { action.WithDefault(columnCopy.DefaultValue); } }); } yield return(command); } }