public async Task <IEnumerable <IFeatureEventContext> > EnableFeatureAsync(string featureId) { // Get features to enable var feature = await _shellDescriptorManager.GetFeatureAsync(featureId); // Ensure we also enable dependencies var featureIds = feature.FeatureDependencies .Select(d => d.ModuleId).ToArray(); // Enable features return(await EnableFeaturesAsync(featureIds)); }
public async Task <ICommandResultBase> UpdateAsync(string moduleId) { var output = new CommandResultBase(); // Get installed feature var feature = await _featureFacade.GetFeatureByIdAsync(moduleId); // Ensure we found the feature if (feature == null) { return(output.Failed( $"A feature named '{moduleId}' could not be found within the ShellFeatures table.")); } // Get available module var module = await _shellDescriptorManager.GetFeatureAsync(moduleId); // Ensure we found the module if (module == null) { return(output.Failed($"A module named '{moduleId}' could not be found on the file system. Please ensure the '{moduleId}' module exists within the root/modules folder.")); } // ------------------------------------------------------------------ // 1. Check to ensure we have a newer version of the module // ------------------------------------------------------------------ var from = feature.Version.ToVersion(); var to = module.Descriptor.Version.ToVersion(); if (from == null) { return(output.Failed( $"Could not convert version for feature {feature.ModuleId} of {feature.Version} to a valid version. Please check the version within the shell features database table.")); } if (to == null) { return(output.Failed( $"Could not convert version for module {module.Descriptor.Id} of {module.Descriptor.Version} to a valid version. Please check the version within the modules manifest file.")); } // No newer version simply return if (from >= to) { return(output.Success()); } // ------------------------------------------------------------------ // 2. Check to ensure the module we are updating is compatible // with the current version of Plato we are running // ------------------------------------------------------------------ var modulePlatoVersion = module.Descriptor.PlatoVersion.ToVersion(); // Does the module have a Plato version defined? if (modulePlatoVersion != null) { // Get current Plato version var currentPlatoVersion = _platoOptions.Value.Version.ToVersion(); if (currentPlatoVersion != null) { // Does the module require a newer version of Plato? if (modulePlatoVersion > currentPlatoVersion) { return(output.Failed( $"{moduleId} {module.Descriptor.Version} requires Plato {modulePlatoVersion.ToString()} whilst you are running Plato {currentPlatoVersion.ToString()}. Please upgrade to Plato {modulePlatoVersion.ToString()} and try updating {moduleId} again.")); } } } // ------------------------------------------------------------------ // 3. Invoke FeatureEventHandlers & database migrations // ------------------------------------------------------------------ var results = await InvokeFeatureEventHandlersAsync( feature, async context => { // The result to return var result = new CommandResultBase(); // Perform migrations from current installed feature version // to latest available version defined via the modules IMigrationProvider // All versions between from and to var versions = from.GetVersionsBetween(to); // Compile versions to search var versionsToSearch = versions != null ? versions?.ToList().Select(v => v.ToString()) : new List <string>(); // Build migrations for feature & versions var migrations = _migrationBuilder.BuildMigrations(moduleId, versionsToSearch.ToArray()); // Apply migrations var migrationResults = await migrations.ApplyMigrationsAsync(); // We may not have migrations if (migrationResults != null) { // Did any errors occur whilst applying the migration? if (migrationResults.Errors.Any()) { var errors = new List <CommandError>(); foreach (var error in migrationResults.Errors) { errors.Add(new CommandError(error.Message)); } return(result.Failed(errors.ToArray())); } } // If we reach this point everything went OK, Migrations applied // successfully and no errors occurred within the features update handlers. // Finally update the features version within the ShellFeatures table to reflect // the new version of the module we've just updated to, also update // shell descriptor to reflect version changes within dictionary store var updateResult = await UpdateShellFeatureVersionAsync(feature, module.Descriptor.Version); if (updateResult.Errors.Any()) { return(result.Failed(updateResult.Errors.ToArray())); } // Return success return(result.Success()); }); // Did any errors occur? var handlerErrors = results .Where(c => c.Value.Errors.Any()) .SelectMany(h => h.Value.Errors) .ToList(); if (handlerErrors.Count > 0) { var errors = new List <CommandError>(); foreach (var error in handlerErrors) { errors.Add(new CommandError(error.Value)); } return(output.Failed(errors.ToArray())); } // No errors, recycle shell context to apply updates RecycleShell(); return(output.Success()); }