/// <summary> /// Rebinds the currently-run migrations to the migrations grid. /// </summary> private void BindGrid() { var qry = new PluginMigrationService(new RockContext()).Queryable() .Where(m => !m.PluginAssemblyName.StartsWith("Rock")) .OrderBy(m => m.PluginAssemblyName) .ThenByDescending(m => m.MigrationNumber); gMigrations.DataSource = qry.ToList(); gMigrations.EntityTypeId = EntityTypeCache.Read <PluginMigration>().Id; gMigrations.DataBind(); }
/// <summary> /// Executes a rollback of the given migration (after rolling back all dependent migrations). /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void mdRollbackConfirm_DoRollback(object sender, EventArgs e) { int migrationDbKey = 0; if (!Int32.TryParse(hfRollbackId.Value, out migrationDbKey)) { return; } PluginMigration migration = new PluginMigrationService(new RockContext()).Get(migrationDbKey); if (migration == null) { return; } // run the rollbacks var migrationTypes = GetMigrationsThatCanBeRolledBack( migration.PluginAssemblyName, migration.MigrationNumber ); Exception rollbackError = null; try { RollbackMigrations(migrationTypes); } catch (Exception ex) { rollbackError = ex; } // reset the UI mdRollbackConfirm.Hide(); hfRollbackId.Value = null; // show success/fail message if (rollbackError == null) { maRollbackStatus.Show("All rollbacks successful.", ModalAlertType.Information); } else { string error = "There was an error rolling back a migration. " + "Check the exception log for more details. The migration has not been rolled back."; // TODO include exception message (can't right now--bug with string.EscapeQuotes() causes // the Rock:ModalAlert to issue a JS parse error) maRollbackStatus.Show(error, ModalAlertType.Warning); } BindGrid(); }
/// <summary> /// The commands to run to migrate plugin to the specific version /// </summary> public override void Up() { var migrateNamespace = false; var oldNamespace = "com.kfs.FTPStorageProvider"; // check if migration has previously run using (var rockContext = new RockContext()) { var migrationNumber = (System.Attribute.GetCustomAttribute(this.GetType(), typeof(MigrationNumberAttribute)) as MigrationNumberAttribute).Number; migrateNamespace = new PluginMigrationService(rockContext) .Queryable() .Where(m => m.PluginAssemblyName.Equals(oldNamespace, StringComparison.CurrentCultureIgnoreCase) && m.MigrationNumber == migrationNumber) .Any(); } if (migrateNamespace) { Sql(@" IF EXISTS ( SELECT [Id] FROM [EntityType] WHERE [Guid] = 'DB311F90-0415-4F83-8E61-16BE12C1F89B' ) BEGIN UPDATE [EntityType] SET [Name] = 'rocks.kfs.Storage.Provider.FTP.FTPStorage' WHERE [Guid] = 'DB311F90-0415-4F83-8E61-16BE12C1F89B' END "); } else { RockMigrationHelper.UpdateEntityType("rocks.kfs.Storage.Provider.FTP.FTPStorage", "DB311F90-0415-4F83-8E61-16BE12C1F89B", false, true); RockMigrationHelper.AddEntityAttribute("Rock.Model.BinaryFileType", "9C204CD0-1233-41C5-818A-C5DA439445AA", "StorageEntityTypeId", "0", "FTP Address", "", "Folder to which selected file will be uploaded. Note, the folder must exist on the FTP server. Example: 'ftp://ftp.mysite.com/audio/weekend/'", 0, "", "CC215A28-869A-4713-9AE4-9282562F59FD", null); RockMigrationHelper.AddEntityAttribute("Rock.Model.BinaryFileType", "36167F3E-8CB2-44F9-9022-102F171FBC9A", "StorageEntityTypeId", "0", "Username", "", "The Username to authenticate with.", 1, "", "6B78A006-C8CD-4420-B7FA-08800384402E", null); RockMigrationHelper.AddEntityAttribute("Rock.Model.BinaryFileType", "36167F3E-8CB2-44F9-9022-102F171FBC9A", "StorageEntityTypeId", "0", "Password", "", "The Password to authenticate with.", 2, "", "9B1425A7-6C65-4C87-AB72-AF508A4FF173", null); RockMigrationHelper.AddEntityAttribute("Rock.Model.BinaryFileType", "C0D0D7E2-C3B0-4004-ABEA-4BBFAD10D5D2", "StorageEntityTypeId", "0", "Public Access URL", "", "The public URL of the content folder. Example: 'https://www.mysite.com/ftp/audio/weekend/'", 3, "", "9F77C47E-D56A-498D-871D-D63A27E1E88C", null); Sql(@" DECLARE @FTPStorageId int = ( SELECT TOP 1 [Id] FROM [EntityType] WHERE [Guid] = 'DB311F90-0415-4F83-8E61-16BE12C1F89B' ) UPDATE [Attribute] SET [EntityTypeQualifierValue] = CAST(@FTPStorageId as varchar) WHERE [Guid] IN ( 'CC215A28-869A-4713-9AE4-9282562F59FD', '6B78A006-C8CD-4420-B7FA-08800384402E', '9B1425A7-6C65-4C87-AB72-AF508A4FF173', '9F77C47E-D56A-498D-871D-D63A27E1E88C' ) "); RockMigrationHelper.UpdateAttributeQualifier("9B1425A7-6C65-4C87-AB72-AF508A4FF173", "ispassword", "True", "BCAD2656-AB88-4120-954D-0C96142309F7"); } }
/// <summary> /// Shows a dialog asking the user to confirm if they'd like to roll back the specified migration(s). /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void gMigrations_ConfirmRollback(object sender, RowEventArgs e) { // determine the migrations that'll be rolled back int migrationDbKey = (int)e.RowKeyValue; PluginMigration migration = new PluginMigrationService(new RockContext()).Get(migrationDbKey); var migrationTypes = GetMigrationsThatCanBeRolledBack( migration.PluginAssemblyName, migration.MigrationNumber ); // populate the modal's contents hfRollbackId.Value = migrationDbKey.ToString(); string warning = "<p>This will rollback the following migrations:</p>"; warning += MigrationTypesToHtmlList(migrationTypes); warning += "<p>Are you sure you want to do this?</p>"; nbRollbackInfo.Title = warning; mdRollbackConfirm.Show(); }
/// <summary> /// Rolls back the given migration type. That is, executes the Down() method on the migration and /// updates the plugin migrations table to show the migration isn't currently applied to the database. /// </summary> /// <param name="migrationType">The migration type to roll back.</param> /// <param name="con">The database connection on which to execute the rollback.</param> private void RollbackMigration(Type migrationType, SqlConnection con) { using (var sqlTxn = con.BeginTransaction()) { bool transactionActive = true; try { // Create an instance of the migration and run the down action var migration = Activator.CreateInstance(migrationType) as Migration; migration.SqlConnection = con; migration.SqlTransaction = sqlTxn; migration.Down(); sqlTxn.Commit(); transactionActive = false; // Remove the plugin migration record to indicate that this migration isn't currently applied var rockContext = new RockContext(); var pluginMigrationService = new PluginMigrationService(rockContext); string assemblyName = migrationType.Assembly.GetName().Name; int migrationNumber = GetMigrationNumberForMigrationType(migrationType).Number; string migrationName = migrationType.Name; var migrationRecord = pluginMigrationService .Queryable() .Where(pm => pm.PluginAssemblyName == assemblyName) .Where(pm => pm.MigrationNumber == migrationNumber) .Where(pm => pm.MigrationName == migrationName) .First(); pluginMigrationService.Delete(migrationRecord); rockContext.SaveChanges(); } catch (Exception ex) { if (transactionActive) { sqlTxn.Rollback(); } throw ex; } } }
/// <summary> /// Runs the plugin migrations for the specified plugin assembly /// </summary> /// <param name="pluginAssembly">The plugin assembly.</param> /// <returns></returns> /// <exception cref="RockStartupException"> /// The '{assemblyName}' plugin assembly contains duplicate migration numbers ({ migrationNumberAttr.Number}). /// or /// ##Plugin Migration error occurred in {assemblyMigrations.Key}, {migrationType.Value.Name}## /// </exception> public static bool RunPluginMigrations(Assembly pluginAssembly) { string pluginAssemblyName = pluginAssembly.GetName().Name; // Migrate any plugins from the plugin assembly that have pending migrations List <Type> pluginMigrationTypes = Rock.Reflection.SearchAssembly(pluginAssembly, typeof(Rock.Plugin.Migration)).Select(a => a.Value).ToList(); // If any plugin migrations types were found if (!pluginMigrationTypes.Any()) { return(false); } bool result = false; // Get the current rock version var rockVersion = new Version(Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber()); // put the migrations to run in a Dictionary so that we can run them in the correct order // based on MigrationNumberAttribute var migrationTypesByNumber = new Dictionary <int, Type>(); // Iterate plugin migrations foreach (var migrationType in pluginMigrationTypes) { // Get the MigrationNumberAttribute for the migration var migrationNumberAttr = migrationType.GetCustomAttribute <Rock.Plugin.MigrationNumberAttribute>(); if (migrationNumberAttr != null) { // If the migration's minimum Rock version is less than or equal to the current rock version, add it to the list var minRockVersion = new Version(migrationNumberAttr.MinimumRockVersion); if (minRockVersion.CompareTo(rockVersion) <= 0) { // Check to make sure no another migration has same number if (migrationTypesByNumber.ContainsKey(migrationNumberAttr.Number)) { throw new RockStartupException($"The '{pluginAssemblyName}' plugin assembly contains duplicate migration numbers ({ migrationNumberAttr.Number})."); } migrationTypesByNumber.Add(migrationNumberAttr.Number, migrationType); } } } // Create EF service for plugin migrations var rockContext = new RockContext(); var pluginMigrationService = new PluginMigrationService(rockContext); // Get the versions that have already been installed var installedMigrationNumbers = pluginMigrationService.Queryable() .Where(m => m.PluginAssemblyName == pluginAssemblyName) .Select(a => a.MigrationNumber); // narrow it down to migrations that haven't already been installed migrationTypesByNumber = migrationTypesByNumber .Where(a => !installedMigrationNumbers.Contains(a.Key)) .ToDictionary(k => k.Key, v => v.Value); // Iterate each migration in the assembly in MigrationNumber order var migrationTypesToRun = migrationTypesByNumber.OrderBy(a => a.Key).Select(a => a.Value).ToList(); var configConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RockContext"]?.ConnectionString; try { using (var sqlConnection = new SqlConnection(configConnectionString)) { try { sqlConnection.Open(); } catch (SqlException ex) { throw new RockStartupException("Error connecting to the SQL database. Please check the 'RockContext' connection string in the web.ConnectionString.config file.", ex); } // Iterate thru each plugin migration in this assembly, if one fails, will log the exception and stop running migrations for this assembly foreach (Type migrationType in migrationTypesToRun) { int migrationNumber = migrationType.GetCustomAttribute <Rock.Plugin.MigrationNumberAttribute>().Number; using (var sqlTxn = sqlConnection.BeginTransaction()) { bool transactionActive = true; try { // Create an instance of the migration and run the up migration var migration = Activator.CreateInstance(migrationType) as Rock.Plugin.Migration; migration.SqlConnection = sqlConnection; migration.SqlTransaction = sqlTxn; migration.Up(); sqlTxn.Commit(); transactionActive = false; // Save the plugin migration version so that it is not run again var pluginMigration = new PluginMigration(); pluginMigration.PluginAssemblyName = pluginAssemblyName; pluginMigration.MigrationNumber = migrationNumber; pluginMigration.MigrationName = migrationType.Name; pluginMigrationService.Add(pluginMigration); rockContext.SaveChanges(); result = true; } catch (Exception ex) { if (transactionActive) { sqlTxn.Rollback(); } throw new RockStartupException($"##Plugin Migration error occurred in { migrationNumber}, {migrationType.Name}##", ex); } } } } } catch (RockStartupException rockStartupException) { // if a plugin migration got an error, it gets wrapped with a RockStartupException // If this occurs, we'll log the migration that occurred, and stop running migrations for this assembly System.Diagnostics.Debug.WriteLine(rockStartupException.Message); LogError(rockStartupException, null); } catch (Exception ex) { // If an exception occurs in an an assembly, log the error, and stop running migrations for this assembly var startupException = new RockStartupException($"Error running migrations from {pluginAssemblyName}"); System.Diagnostics.Debug.WriteLine(startupException.Message); LogError(ex, null); } return(result); }
/// <summary> /// Migrates the plugins. /// </summary> /// <param name="rockContext">The rock context.</param> /// <returns></returns> /// <exception cref="System.Exception"> /// Could not connect to the SQL database! Please check the 'RockContext' connection string in the web.ConnectionString.config file. /// or /// </exception> public bool MigratePlugins(RockContext rockContext) { bool result = false; // Migrate any plugins that have pending migrations List <Type> migrationList = Rock.Reflection.FindTypes(typeof(Migration)).Select(a => a.Value).ToList(); // If any plugin migrations types were found if (migrationList.Any()) { // Create EF service for plugin migrations var pluginMigrationService = new PluginMigrationService(rockContext); // Get the current rock version var rockVersion = new Version(Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber()); // Create dictionary for holding migrations specific to an assembly var assemblies = new Dictionary <string, Dictionary <int, Type> >(); // Iterate plugin migrations foreach (var migrationType in migrationList) { // Get the MigrationNumberAttribute for the migration var migrationNumberAttr = System.Attribute.GetCustomAttribute(migrationType, typeof(MigrationNumberAttribute)) as MigrationNumberAttribute; if (migrationNumberAttr != null) { // If the migration's minimum Rock version is less than or equal to the current rock version, add it to the list var minRockVersion = new Version(migrationNumberAttr.MinimumRockVersion); if (minRockVersion.CompareTo(rockVersion) <= 0) { string assemblyName = migrationType.Assembly.GetName().Name; if (!assemblies.ContainsKey(assemblyName)) { assemblies.Add(assemblyName, new Dictionary <int, Type>()); } // Check to make sure no another migration has same number if (assemblies[assemblyName].ContainsKey(migrationNumberAttr.Number)) { throw new Exception(string.Format("The '{0}' plugin assembly contains duplicate migration numbers ({1}).", assemblyName, migrationNumberAttr.Number)); } assemblies[assemblyName].Add(migrationNumberAttr.Number, migrationType); } } } var configConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RockContext"]; if (configConnectionString != null) { string connectionString = configConnectionString.ConnectionString; if (!string.IsNullOrWhiteSpace(connectionString)) { using (SqlConnection con = new SqlConnection(connectionString)) { try { con.Open(); } catch (SqlException ex) { throw new Exception("Could not connect to the SQL database! Please check the 'RockContext' connection string in the web.ConnectionString.config file.", ex); } // Iterate each assembly that contains plugin migrations foreach (var assemblyMigrations in assemblies) { try { // Get the versions that have already been installed var installedVersions = pluginMigrationService.Queryable() .Where(m => m.PluginAssemblyName == assemblyMigrations.Key) .ToList(); // Iterate each migration in the assembly in MigrationNumber order foreach (var migrationType in assemblyMigrations.Value.OrderBy(t => t.Key)) { // Check to make sure migration has not already been run if (!installedVersions.Any(v => v.MigrationNumber == migrationType.Key)) { using (var sqlTxn = con.BeginTransaction()) { bool transactionActive = true; try { // Create an instance of the migration and run the up migration var migration = Activator.CreateInstance(migrationType.Value) as Rock.Plugin.Migration; migration.SqlConnection = con; migration.SqlTransaction = sqlTxn; migration.Up(); sqlTxn.Commit(); transactionActive = false; // Save the plugin migration version so that it is not run again var pluginMigration = new PluginMigration(); pluginMigration.PluginAssemblyName = assemblyMigrations.Key; pluginMigration.MigrationNumber = migrationType.Key; pluginMigration.MigrationName = migrationType.Value.Name; pluginMigrationService.Add(pluginMigration); rockContext.SaveChanges(); result = true; } catch (Exception ex) { if (transactionActive) { sqlTxn.Rollback(); } throw new Exception(string.Format("Plugin Migration error occurred in {0}, {1}", assemblyMigrations.Key, migrationType.Value.Name), ex); } } } } } catch (Exception ex) { // If an exception occurs in an an assembly, log the error, and continue with next assembly LogError(ex, null); } } } } } } return(result); }
/// <summary> /// The commands to run to migrate plugin to the specific version /// </summary> public override void Up() { var migrateNamespaceEmail = false; var migrateNamespaceSMS = false; var oldNamespaceEmail = "com.kfs.GroupScheduledEmails"; var oldNamespaceSMS = "com.kfs.GroupScheduledSMS"; // check if migration has previously run using (var rockContext = new RockContext()) { var migrationNumber = (System.Attribute.GetCustomAttribute(this.GetType(), typeof(MigrationNumberAttribute)) as MigrationNumberAttribute).Number; migrateNamespaceEmail = new PluginMigrationService(rockContext) .Queryable() .Where(m => m.PluginAssemblyName.Equals(oldNamespaceEmail, StringComparison.CurrentCultureIgnoreCase) && m.MigrationNumber == migrationNumber) .Any(); migrateNamespaceSMS = new PluginMigrationService(rockContext) .Queryable() .Where(m => m.PluginAssemblyName.Equals(oldNamespaceSMS, StringComparison.CurrentCultureIgnoreCase) && m.MigrationNumber == migrationNumber) .Any(); } #region Email Attributes if (migrateNamespaceEmail) { var attributeMatrixTemplateEmailId = new AttributeMatrixTemplateService(new RockContext()).Get(KFSConst.Attribute.ATTRIBUTE_MATRIX_TEMPLATE_SCHEDULED_EMAILS.AsGuid()).Id.ToString(); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "rocks.kfs.ScheduledGroupCommunication.EmailSendDateTime", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.DATE_TIME, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_FROM_EMAIL, "rocks.kfs.ScheduledGroupCommunication.EmailFromAddress", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.EMAIL, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_FROM_NAME, "rocks.kfs.ScheduledGroupCommunication.EmailFromName", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.TEXT, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SUBJECT, "rocks.kfs.ScheduledGroupCommunication.EmailSubject", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.TEXT, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_MESSAGE, "rocks.kfs.ScheduledGroupCommunication.EmailMessage", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.HTML, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId); using (var rockContext = new RockContext()) { // look for any configured jobs and change the class name var emailJobs = new ServiceJobService(rockContext) .Queryable() .Where(j => j.Class.Equals("com.kfs.GroupScheduledEmails.Jobs.SendScheduledGroupEmail", StringComparison.CurrentCultureIgnoreCase)) .ToList(); foreach (var job in emailJobs) { job.Class = "rocks.kfs.ScheduledGroupCommunication.Jobs.SendScheduledGroupEmail"; } // look for job attributes and change qualifier value var attributes = new AttributeService(rockContext) .Queryable() .Where(a => a.EntityTypeQualifierValue.Equals("com.kfs.GroupScheduledEmails.Jobs.SendScheduledGroupEmail", StringComparison.CurrentCultureIgnoreCase)) .ToList(); foreach (var attribute in attributes) { attribute.EntityTypeQualifierValue = "rocks.kfs.ScheduledGroupCommunication.Jobs.SendScheduledGroupEmail"; } rockContext.SaveChanges(); } } else { // create the attribute matrix template and get it's id to assign to the attributes we'll create var attributeMatrixTemplateEmail = new AttributeMatrixTemplate { Name = "Scheduled Emails", Description = "Used to create scheduled emails.", IsActive = true, FormattedLava = AttributeMatrixTemplate.FormattedLavaDefault, CreatedDateTime = RockDateTime.Now, Guid = KFSConst.Attribute.ATTRIBUTE_MATRIX_TEMPLATE_SCHEDULED_EMAILS.AsGuid() }; var rockContextEmail = new RockContext(); rockContextEmail.WrapTransaction(() => { rockContextEmail.AttributeMatrixTemplates.Add(attributeMatrixTemplateEmail); rockContextEmail.SaveChanges(); }); var attributeMatrixTemplateEmailId = new AttributeMatrixTemplateService(rockContextEmail).Get(KFSConst.Attribute.ATTRIBUTE_MATRIX_TEMPLATE_SCHEDULED_EMAILS.AsGuid()).Id.ToString(); // send date time RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.DATE_TIME, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId, "Send Date Time", "", 0, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "rocks.kfs.ScheduledGroupCommunication.EmailSendDateTime"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "datePickerControlType", "Date Picker", "3C8A1A23-F2CD-42F6-BF1E-69AAE87A4701"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "displayCurrentOption", "False", "EE2C58B0-5A24-4957-A84D-94829985B2C1"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "displayDiff", "False", "B61EB1C8-D811-4D4A-9AC9-2E8B8381E468"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "format", "", "83C6F1A4-2514-4C62-A4EA-FD804ABC758C"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SEND_DATE, "futureYearCount", "", "1AFFC6EA-8C45-4125-94DC-25E0E73D8CC6"); // from email RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.EMAIL, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId, "From Email", "", 1, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_FROM_EMAIL, "rocks.kfs.ScheduledGroupCommunication.EmailFromAddress"); // from name RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.TEXT, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId, "From Name", "", 2, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_FROM_NAME, "rocks.kfs.ScheduledGroupCommunication.EmailFromName"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_FROM_NAME, "ispassword", "false", "1EE77F52-992D-43CE-8574-306E95A7D740"); // subject RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.TEXT, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId, "Subject", "", 3, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SUBJECT, "rocks.kfs.ScheduledGroupCommunication.EmailSubject"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_SUBJECT, "ispassword", "false", "CEB3BEB8-20E9-4A8F-8530-2B68DA02B020"); // message RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.HTML, "AttributeMatrixTemplateId", attributeMatrixTemplateEmailId, "Message", "", 4, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_MESSAGE, "rocks.kfs.ScheduledGroupCommunication.EmailMessage"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_MESSAGE, "documentfolderroot", "", "4B2FFA29-5B9C-4F74-ACE5-54C97B68E0B6"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_MESSAGE, "imagefolderroot", "", "77C6B7A9-69DF-466F-AFEC-DC41B33E0DF0"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_MESSAGE, "toolbar", "Light", "E1E5C3F2-F64C-4942-A5B3-B712125BF8CB"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_EMAIL_MESSAGE, "userspecificroot", "False", "C3FF1EBB-7EFF-4747-A326-F6BCD669DD35"); // set all attributes to be required Sql(@" UPDATE [Attribute] SET [IsRequired] = 1 WHERE ( [Guid] = '39A38B02-112C-4EDC-A30E-4BDB1B090EE4' OR [Guid] = 'F7C73002-6442-4756-BFDB-BC0BFE58EF15' OR [Guid] = '7BEE419A-8444-44E1-B7EB-451C038977B3' OR [Guid] = '9EC7C8A9-F4C9-421C-9129-2DD023E09D05' OR [Guid] = '8C4EE7A8-086D-42B7-908F-77A9A36E5342' ) "); } #endregion #region SMS Attributes if (migrateNamespaceSMS) { var attributeMatrixTemplateSMSId = new AttributeMatrixTemplateService(new RockContext()).Get(KFSConst.Attribute.ATTRIBUTE_MATRIX_TEMPLATE_SCHEDULED_SMS.AsGuid()).Id.ToString(); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "rocks.kfs.ScheduledGroupCommunication.SMSSendDateTime", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.DATE_TIME, "AttributeMatrixTemplateId", attributeMatrixTemplateSMSId); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_FROM_NUMBER, "rocks.kfs.ScheduledGroupCommunication.SMSFromNumber", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.DEFINED_VALUE, "AttributeMatrixTemplateId", attributeMatrixTemplateSMSId); RockMigrationHelper.EnsureAttributeByGuid(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_MESSAGE, "rocks.kfs.ScheduledGroupCommunication.SMSMessage", "3c9d5021-0484-4846-aef6-b6216d26c3c8", Rock.SystemGuid.FieldType.MEMO, "AttributeMatrixTemplateId", attributeMatrixTemplateSMSId); using (var rockContext = new RockContext()) { // look for any configured jobs and change the class name var smsJobs = new ServiceJobService(rockContext) .Queryable() .Where(j => j.Class.Equals("com.kfs.GroupScheduledSMS.Jobs.SendScheduledGroupSMS", StringComparison.CurrentCultureIgnoreCase)) .ToList(); foreach (var job in smsJobs) { job.Class = "rocks.kfs.ScheduledGroupCommunication.Jobs.SendScheduledGroupSMS"; } // look for job attributes and change qualifier value var attributes = new AttributeService(rockContext) .Queryable() .Where(a => a.EntityTypeQualifierValue.Equals("com.kfs.GroupScheduledSMS.Jobs.SendScheduledGroupSMS", StringComparison.CurrentCultureIgnoreCase)) .ToList(); foreach (var attribute in attributes) { attribute.EntityTypeQualifierValue = "rocks.kfs.ScheduledGroupCommunication.Jobs.SendScheduledGroupSMS"; } rockContext.SaveChanges(); } } else { var attributeMatrixTemplateSMS = new AttributeMatrixTemplate { Name = "Scheduled SMS Messages", Description = "Used to create scheduled SMS messages.", IsActive = true, FormattedLava = AttributeMatrixTemplate.FormattedLavaDefault, CreatedDateTime = RockDateTime.Now, Guid = KFSConst.Attribute.ATTRIBUTE_MATRIX_TEMPLATE_SCHEDULED_SMS.AsGuid() }; var rockContextSMS = new RockContext(); rockContextSMS.WrapTransaction(() => { rockContextSMS.AttributeMatrixTemplates.Add(attributeMatrixTemplateSMS); rockContextSMS.SaveChanges(); }); var attributeMatrixTemplateSMSId = new AttributeMatrixTemplateService(rockContextSMS).Get(KFSConst.Attribute.ATTRIBUTE_MATRIX_TEMPLATE_SCHEDULED_SMS.AsGuid()).Id.ToString(); // send date time RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.DATE_TIME, "AttributeMatrixTemplateId", attributeMatrixTemplateSMSId, "Send Date Time", "", 0, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "rocks.kfs.ScheduledGroupCommunication.SMSSendDateTime"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "datePickerControlType", "Date Picker", "3C8A1A23-F2CD-42F6-BF1E-69AAE87A4701"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "displayCurrentOption", "False", "EE2C58B0-5A24-4957-A84D-94829985B2C1"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "displayDiff", "False", "B61EB1C8-D811-4D4A-9AC9-2E8B8381E468"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "format", "", "83C6F1A4-2514-4C62-A4EA-FD804ABC758C"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_SEND_DATE, "futureYearCount", "", "1AFFC6EA-8C45-4125-94DC-25E0E73D8CC6"); // from number RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.DEFINED_VALUE, "AttributeMatrixTemplateId", attributeMatrixTemplateSMSId, "From Number", "", 1, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_FROM_NUMBER, "rocks.kfs.ScheduledGroupCommunication.SMSFromNumber"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_FROM_NUMBER, "allowmultiple", "False", "90051033-C881-42E8-A0CE-4152527D6FA3"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_FROM_NUMBER, "definedtype", "", "26143779-5747-416C-98B9-EBC86E4B8EE6"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_FROM_NUMBER, "displaydescription", "True", "8AABC104-CFE5-4DF1-A164-2DA305F46BBC"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_FROM_NUMBER, "enhancedselection", "False", "B0008343-0033-4194-A1A8-F5AEF3B095AD"); // message RockMigrationHelper.UpdateEntityAttribute("Rock.Model.AttributeMatrixItem", Rock.SystemGuid.FieldType.MEMO, "AttributeMatrixTemplateId", attributeMatrixTemplateSMSId, "Message", "", 2, "", KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_MESSAGE, "rocks.kfs.ScheduledGroupCommunication.SMSMessage"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_MESSAGE, "numberofrows", "3", "BB1F72CF-46E3-4ED5-B7C8-BAD274744435"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_MESSAGE, "allowhtml", "False", "0C97ED08-FF8D-4BF3-ADD1-C688EFB999D1"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_MESSAGE, "maxcharacters", "160", "A54E62A3-05BF-4458-8F56-408A2132BDA7"); RockMigrationHelper.AddAttributeQualifier(KFSConst.Attribute.MATRIX_ATTRIBUTE_SMS_MESSAGE, "showcountdown", "True", "8808BF22-2051-488F-83E5-7188D2941334"); // set all attributes to be required Sql(@" UPDATE [Attribute] SET [IsRequired] = 1 WHERE ( [Guid] = 'B2125940-565B-42CE-82BE-CDA58FC65FDE' OR [Guid] = '1984A561-C4A9-4D4F-B366-23AD54BDCFE8' OR [Guid] = 'C57166D5-C0D3-4DA6-88DD-92AFA5126D69' ) DECLARE @CommunicationSMSFromDefinedTypeId int = ( SELECT TOP 1 [Id] FROM [DefinedType] WHERE [Guid] = '611BDE1F-7405-4D16-8626-CCFEDB0E62BE' ) UPDATE [AttributeQualifier] SET [Value] = CAST( @CommunicationSMSFromDefinedTypeId AS varchar ) WHERE [Guid] = '26143779-5747-416C-98B9-EBC86E4B8EE6' "); } #endregion }
/// <summary> /// Migrates the database. /// </summary> /// <returns>True if at least one migration was run</returns> public bool MigrateDatabase( RockContext rockContext ) { bool result = false; var fileInfo = new FileInfo( Server.MapPath( "~/App_Data/Run.Migration" ) ); if ( fileInfo.Exists ) { Database.SetInitializer( new MigrateDatabaseToLatestVersion<Rock.Data.RockContext, Rock.Migrations.Configuration>() ); // explictly check if the database exists, and force create it if doesn't exist if ( !rockContext.Database.Exists() ) { // If database did not exist, initialize a database (which runs existing Rock migrations) rockContext.Database.Initialize( true ); result = true; } else { // If database does exist, run any pending Rock migrations var migrator = new System.Data.Entity.Migrations.DbMigrator( new Rock.Migrations.Configuration() ); if ( migrator.GetPendingMigrations().Any() ) { migrator.Update(); result = true; } } fileInfo.Delete(); } else { // default Initializer is CreateDatabaseIfNotExists, but we don't want that to happen if automigrate is false, so set it to NULL so that nothing happens Database.SetInitializer<Rock.Data.RockContext>( null ); } // Migrate any plugins that have pending migrations List<Type> migrationList = Rock.Reflection.FindTypes( typeof( Migration ) ).Select( a => a.Value ).ToList(); // If any plugin migrations types were found if ( migrationList.Any() ) { // Create EF service for plugin migrations var pluginMigrationService = new PluginMigrationService( rockContext ); // Get the current rock version var rockVersion = new Version( Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber() ); // Create dictionary for holding migrations specific to an assembly var assemblies = new Dictionary<string, Dictionary<int, Type>>(); // Iterate plugin migrations foreach ( var migrationType in migrationList ) { // Get the MigrationNumberAttribute for the migration var migrationNumberAttr = System.Attribute.GetCustomAttribute( migrationType, typeof( MigrationNumberAttribute ) ) as MigrationNumberAttribute; if ( migrationNumberAttr != null ) { // If the migration's minimum Rock version is less than or equal to the current rock version, add it to the list var minRockVersion = new Version( migrationNumberAttr.MinimumRockVersion ); if ( minRockVersion.CompareTo( rockVersion ) <= 0 ) { string assemblyName = migrationType.Assembly.GetName().Name; if ( !assemblies.ContainsKey( assemblyName ) ) { assemblies.Add( assemblyName, new Dictionary<int, Type>() ); } assemblies[assemblyName].Add( migrationNumberAttr.Number, migrationType ); } } } var configConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RockContext"]; if ( configConnectionString != null ) { string connectionString = configConnectionString.ConnectionString; if ( !string.IsNullOrWhiteSpace( connectionString ) ) { using ( SqlConnection con = new SqlConnection( connectionString ) ) { con.Open(); // Iterate each assembly that contains plugin migrations foreach ( var assemblyMigrations in assemblies ) { try { // Get the versions that have already been installed var installedVersions = pluginMigrationService.Queryable() .Where( m => m.PluginAssemblyName == assemblyMigrations.Key ) .ToList(); // Iterate each migration in the assembly in MigrationNumber order foreach ( var migrationType in assemblyMigrations.Value.OrderBy( t => t.Key ) ) { // Check to make sure migration has not already been run if ( !installedVersions.Any( v => v.MigrationNumber == migrationType.Key ) ) { using ( var sqlTxn = con.BeginTransaction() ) { bool transactionActive = true; try { // Create an instance of the migration and run the up migration var migration = Activator.CreateInstance( migrationType.Value ) as Rock.Plugin.Migration; migration.SqlConnection = con; migration.SqlTransaction = sqlTxn; migration.Up(); sqlTxn.Commit(); transactionActive = false; // Save the plugin migration version so that it is not run again var pluginMigration = new PluginMigration(); pluginMigration.PluginAssemblyName = assemblyMigrations.Key; pluginMigration.MigrationNumber = migrationType.Key; pluginMigration.MigrationName = migrationType.Value.Name; pluginMigrationService.Add( pluginMigration ); rockContext.SaveChanges(); result = true; } catch ( Exception ex ) { if ( transactionActive ) { sqlTxn.Rollback(); } throw new Exception( string.Format( "Plugin Migration error occurred in {0}, {1}", assemblyMigrations.Key, migrationType.Value.Name ), ex ); } } } } } catch ( Exception ex ) { // If an exception occurs in an an assembly, log the error, and continue with next assembly LogError( ex, null ); } } } } } } return result; }
/// <summary> /// Migrates the plugins. /// </summary> /// <param name="rockContext">The rock context.</param> /// <returns></returns> /// <exception cref="System.Exception"> /// Could not connect to the SQL database! Please check the 'RockContext' connection string in the web.ConnectionString.config file. /// or /// </exception> public bool MigratePlugins( RockContext rockContext ) { bool result = false; // Migrate any plugins that have pending migrations List<Type> migrationList = Rock.Reflection.FindTypes( typeof( Migration ) ).Select( a => a.Value ).ToList(); // If any plugin migrations types were found if ( migrationList.Any() ) { // Create EF service for plugin migrations var pluginMigrationService = new PluginMigrationService( rockContext ); // Get the current rock version var rockVersion = new Version( Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber() ); // Create dictionary for holding migrations specific to an assembly var assemblies = new Dictionary<string, Dictionary<int, Type>>(); // Iterate plugin migrations foreach ( var migrationType in migrationList ) { // Get the MigrationNumberAttribute for the migration var migrationNumberAttr = System.Attribute.GetCustomAttribute( migrationType, typeof( MigrationNumberAttribute ) ) as MigrationNumberAttribute; if ( migrationNumberAttr != null ) { // If the migration's minimum Rock version is less than or equal to the current rock version, add it to the list var minRockVersion = new Version( migrationNumberAttr.MinimumRockVersion ); if ( minRockVersion.CompareTo( rockVersion ) <= 0 ) { string assemblyName = migrationType.Assembly.GetName().Name; if ( !assemblies.ContainsKey( assemblyName ) ) { assemblies.Add( assemblyName, new Dictionary<int, Type>() ); } assemblies[assemblyName].Add( migrationNumberAttr.Number, migrationType ); } } } var configConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RockContext"]; if ( configConnectionString != null ) { string connectionString = configConnectionString.ConnectionString; if ( !string.IsNullOrWhiteSpace( connectionString ) ) { using ( SqlConnection con = new SqlConnection( connectionString ) ) { try { con.Open(); } catch ( SqlException ex ) { throw new Exception( "Could not connect to the SQL database! Please check the 'RockContext' connection string in the web.ConnectionString.config file.", ex ); } // Iterate each assembly that contains plugin migrations foreach ( var assemblyMigrations in assemblies ) { try { // Get the versions that have already been installed var installedVersions = pluginMigrationService.Queryable() .Where( m => m.PluginAssemblyName == assemblyMigrations.Key ) .ToList(); // Iterate each migration in the assembly in MigrationNumber order foreach ( var migrationType in assemblyMigrations.Value.OrderBy( t => t.Key ) ) { // Check to make sure migration has not already been run if ( !installedVersions.Any( v => v.MigrationNumber == migrationType.Key ) ) { using ( var sqlTxn = con.BeginTransaction() ) { bool transactionActive = true; try { // Create an instance of the migration and run the up migration var migration = Activator.CreateInstance( migrationType.Value ) as Rock.Plugin.Migration; migration.SqlConnection = con; migration.SqlTransaction = sqlTxn; migration.Up(); sqlTxn.Commit(); transactionActive = false; // Save the plugin migration version so that it is not run again var pluginMigration = new PluginMigration(); pluginMigration.PluginAssemblyName = assemblyMigrations.Key; pluginMigration.MigrationNumber = migrationType.Key; pluginMigration.MigrationName = migrationType.Value.Name; pluginMigrationService.Add( pluginMigration ); rockContext.SaveChanges(); result = true; } catch ( Exception ex ) { if ( transactionActive ) { sqlTxn.Rollback(); } throw new Exception( string.Format( "Plugin Migration error occurred in {0}, {1}", assemblyMigrations.Key, migrationType.Value.Name ), ex ); } } } } } catch ( Exception ex ) { // If an exception occurs in an an assembly, log the error, and continue with next assembly LogError( ex, null ); } } } } } } return result; }
/// <summary> /// Migrates the database. /// </summary> public void MigrateDatabase() { // Check if database should be auto-migrated for the core and plugins if ( ConfigurationManager.AppSettings["AutoMigrateDatabase"].AsBoolean( true ) ) { try { Database.SetInitializer( new MigrateDatabaseToLatestVersion<Rock.Data.RockContext, Rock.Migrations.Configuration>() ); var rockContext = new RockContext(); // explictly check if the database exists, and force create it if doesn't exist if ( !rockContext.Database.Exists() ) { // If database did not exist, initialize a database (which runs existing Rock migrations) rockContext.Database.Initialize( true ); } else { // If database does exist, run any pending Rock migrations var migrator = new System.Data.Entity.Migrations.DbMigrator( new Rock.Migrations.Configuration() ); migrator.Update(); } // Migrate any plugins that have pending migrations List<Type> migrationList = Rock.Reflection.FindTypes( typeof( Migration ) ).Select( a => a.Value ).ToList(); // If any plugin migrations types were found if ( migrationList.Any() ) { // Create EF service for plugin migrations var pluginMigrationService = new PluginMigrationService( rockContext ); // Get the current rock version var rockVersion = new Version( Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber() ); // Create dictionary for holding migrations specific to an assembly var assemblies = new Dictionary<string, Dictionary<int, Type>>(); // Iterate plugin migrations foreach ( var migrationType in migrationList ) { // Get the MigrationNumberAttribute for the migration var migrationNumberAttr = System.Attribute.GetCustomAttribute( migrationType, typeof( MigrationNumberAttribute ) ) as MigrationNumberAttribute; if ( migrationNumberAttr != null ) { // If the migration's minimum Rock version is less than or equal to the current rock version, add it to the list var minRockVersion = new Version( migrationNumberAttr.MinimumRockVersion ); if ( minRockVersion.CompareTo( rockVersion ) <= 0 ) { string assemblyName = migrationType.Assembly.GetName().Name; if ( !assemblies.ContainsKey( assemblyName ) ) { assemblies.Add( assemblyName, new Dictionary<int, Type>() ); } assemblies[assemblyName].Add( migrationNumberAttr.Number, migrationType ); } } } // Iterate each assembly that contains plugin migrations foreach ( var assemblyMigrations in assemblies ) { try { // Get the versions that have already been installed var installedVersions = pluginMigrationService.Queryable() .Where( m => m.PluginAssemblyName == assemblyMigrations.Key ) .ToList(); // Wrap the migrations for each assembly in a transaction so that if an error with one migration, none of the migrations are persisted RockTransactionScope.WrapTransaction( () => { // Iterate each migration in the assembly in MigrationNumber order foreach ( var migrationType in assemblyMigrations.Value.OrderBy( t => t.Key ) ) { // Check to make sure migration has not already been run if ( !installedVersions.Any( v => v.MigrationNumber == migrationType.Key ) ) { try { // Create an instance of the migration and run the up migration var migration = Activator.CreateInstance( migrationType.Value ) as Rock.Plugin.Migration; migration.Up(); // Save the plugin migration version so that it is not run again var pluginMigration = new PluginMigration(); pluginMigration.PluginAssemblyName = assemblyMigrations.Key; pluginMigration.MigrationNumber = migrationType.Key; pluginMigration.MigrationName = migrationType.Value.Name; pluginMigrationService.Add( pluginMigration ); rockContext.SaveChanges(); } catch ( Exception ex ) { throw new Exception( string.Format( "Plugin Migration error occurred in {0}, {1}", assemblyMigrations.Key, migrationType.Value.Name ), ex ); } } } } ); } catch ( Exception ex ) { // If an exception occurs in an an assembly, log the error, and continue with next assembly LogError( ex, null ); } } } } catch ( Exception ex ) { // if migrations fail, log error and attempt to continue LogError( ex, null ); } } else { // default Initializer is CreateDatabaseIfNotExists, but we don't want that to happen if automigrate is false, so set it to NULL so that nothing happens Database.SetInitializer<Rock.Data.RockContext>( null ); } }
/// <summary> /// Migrates the database. /// </summary> public void MigrateDatabase() { // Check if database should be auto-migrated for the core and plugins if (ConfigurationManager.AppSettings["AutoMigrateDatabase"].AsBoolean(true)) { try { Database.SetInitializer(new MigrateDatabaseToLatestVersion <Rock.Data.RockContext, Rock.Migrations.Configuration>()); var rockContext = new RockContext(); // explictly check if the database exists, and force create it if doesn't exist if (!rockContext.Database.Exists()) { // If database did not exist, initialize a database (which runs existing Rock migrations) rockContext.Database.Initialize(true); } else { // If database does exist, run any pending Rock migrations var migrator = new System.Data.Entity.Migrations.DbMigrator(new Rock.Migrations.Configuration()); migrator.Update(); } // Migrate any plugins that have pending migrations List <Type> migrationList = Rock.Reflection.FindTypes(typeof(Migration)).Select(a => a.Value).ToList(); // If any plugin migrations types were found if (migrationList.Any()) { // Create EF service for plugin migrations var pluginMigrationService = new PluginMigrationService(rockContext); // Get the current rock version var rockVersion = new Version(Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber()); // Create dictionary for holding migrations specific to an assembly var assemblies = new Dictionary <string, Dictionary <int, Type> >(); // Iterate plugin migrations foreach (var migrationType in migrationList) { // Get the MigrationNumberAttribute for the migration var migrationNumberAttr = System.Attribute.GetCustomAttribute(migrationType, typeof(MigrationNumberAttribute)) as MigrationNumberAttribute; if (migrationNumberAttr != null) { // If the migration's minimum Rock version is less than or equal to the current rock version, add it to the list var minRockVersion = new Version(migrationNumberAttr.MinimumRockVersion); if (minRockVersion.CompareTo(rockVersion) <= 0) { string assemblyName = migrationType.Assembly.GetName().Name; if (!assemblies.ContainsKey(assemblyName)) { assemblies.Add(assemblyName, new Dictionary <int, Type>()); } assemblies[assemblyName].Add(migrationNumberAttr.Number, migrationType); } } } // Iterate each assembly that contains plugin migrations foreach (var assemblyMigrations in assemblies) { try { // Get the versions that have already been installed var installedVersions = pluginMigrationService.Queryable() .Where(m => m.PluginAssemblyName == assemblyMigrations.Key) .ToList(); // Wrap the migrations for each assembly in a transaction so that if an error with one migration, none of the migrations are persisted RockTransactionScope.WrapTransaction(() => { // Iterate each migration in the assembly in MigrationNumber order foreach (var migrationType in assemblyMigrations.Value.OrderBy(t => t.Key)) { // Check to make sure migration has not already been run if (!installedVersions.Any(v => v.MigrationNumber == migrationType.Key)) { try { // Create an instance of the migration and run the up migration var migration = Activator.CreateInstance(migrationType.Value) as Rock.Plugin.Migration; migration.Up(); // Save the plugin migration version so that it is not run again var pluginMigration = new PluginMigration(); pluginMigration.PluginAssemblyName = assemblyMigrations.Key; pluginMigration.MigrationNumber = migrationType.Key; pluginMigration.MigrationName = migrationType.Value.Name; pluginMigrationService.Add(pluginMigration); rockContext.SaveChanges(); } catch (Exception ex) { throw new Exception(string.Format("Plugin Migration error occurred in {0}, {1}", assemblyMigrations.Key, migrationType.Value.Name), ex); } } } }); } catch (Exception ex) { // If an exception occurs in an an assembly, log the error, and continue with next assembly LogError(ex, null); } } } } catch (Exception ex) { // if migrations fail, log error and attempt to continue LogError(ex, null); } } else { // default Initializer is CreateDatabaseIfNotExists, but we don't want that to happen if automigrate is false, so set it to NULL so that nothing happens Database.SetInitializer <Rock.Data.RockContext>(null); } }
/// <summary> /// The commands to run to migrate plugin to the specific version /// </summary> public override void Up() { var migrateNamespace = false; var oldNamespace = "com.kfs.ShelbyBatchExport"; // check if migration has previously run using (var rockContext = new RockContext()) { var migrationNumber = (System.Attribute.GetCustomAttribute(this.GetType(), typeof(MigrationNumberAttribute)) as MigrationNumberAttribute).Number; migrateNamespace = new PluginMigrationService(rockContext) .Queryable() .Where(m => m.PluginAssemblyName.Equals(oldNamespace, StringComparison.CurrentCultureIgnoreCase) && m.MigrationNumber == migrationNumber) .Any(); } if (migrateNamespace) { // // keeping from old 1 // // batch export date RockMigrationHelper.EnsureAttributeByGuid("4B6576DD-82F6-419F-8DF0-467D2636822D", "rocks.kfs.ShelbyFinancials.DateExported", Rock.SystemGuid.EntityType.FINANCIAL_BATCH, Rock.SystemGuid.FieldType.DATE_TIME, "", ""); // transaction project RockMigrationHelper.EnsureAttributeByGuid("365134A6-D516-48E0-AC67-A011D5D59D99", "rocks.kfs.ShelbyFinancials.Project", Rock.SystemGuid.EntityType.FINANCIAL_TRANSACTION, Rock.SystemGuid.FieldType.DEFINED_VALUE, "", ""); // transaction detail project RockMigrationHelper.EnsureAttributeByGuid("951FAFFD-0513-4E31-9271-87853469E85E", "rocks.kfs.ShelbyFinancials.Project", Rock.SystemGuid.EntityType.FINANCIAL_TRANSACTION_DETAIL, Rock.SystemGuid.FieldType.DEFINED_VALUE, "", ""); // account default project RockMigrationHelper.EnsureAttributeByGuid("85422EA2-AC4E-44E5-99B9-30C131116734", "rocks.kfs.ShelbyFinancials.Project", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.DEFINED_VALUE, "", ""); // account gl attributes RockMigrationHelper.EnsureAttributeByGuid("A211D2C9-249D-4D33-B120-A3EAB37C1EDF", "rocks.kfs.ShelbyFinancials.Company", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("B83D7934-F85A-42B7-AD0E-B4E16D63C189", "rocks.kfs.ShelbyFinancials.Fund", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("FD4EF8CC-DDB7-4DBD-9FD1-601A0119850B", "rocks.kfs.ShelbyFinancials.DebitAccount", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("2C1EE0CC-D329-453B-B4F0-29549E24ED05", "rocks.kfs.ShelbyFinancials.Department", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("0D114FB9-B1AA-4D6D-B0F3-9BB739710992", "rocks.kfs.ShelbyFinancials.CreditAccount", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); // // keeping from old 2 // // create page for project defined type RockMigrationHelper.AddPage(true, Rock.SystemGuid.Page.ADMINISTRATION_FINANCE, "D65F783D-87A9-4CC9-8110-E83466A0EADB", "Projects", "", "01DAC445-9C4A-4469-9F39-A39549D75CBF", "fa fa-clipboard", "2B630A3B-E081-4204-A3E4-17BB3A5F063D"); // add defined value list block and set to projects defined type RockMigrationHelper.AddBlock(true, "01DAC445-9C4A-4469-9F39-A39549D75CBF", "", "0AB2D5E9-9272-47D5-90E4-4AA838D2D3EE", "Projects", "Main", "", "", 0, "23D1B7CE-D70C-4D81-B0D9-534A6D0542DC"); RockMigrationHelper.AddBlockAttributeValue(true, "23D1B7CE-D70C-4D81-B0D9-534A6D0542DC", "9280D61F-C4F3-4A3E-A9BB-BCD67FF78637", "2CE68D65-7EAC-4D5E-80B6-6FB903726961"); // // keeping from old 3 // // nothing // // keeping from old 4 // // transaction project RockMigrationHelper.UpdateAttributeQualifier("365134A6-D516-48E0-AC67-A011D5D59D99", "displaydescription", "True", "4287FEEF-4AB5-4F16-A872-546A393F2DB8"); // transaction detail project RockMigrationHelper.UpdateAttributeQualifier("951FAFFD-0513-4E31-9271-87853469E85E", "displaydescription", "True", "A0679A5F-A76A-4408-9900-C576CC20E18F"); // account default project RockMigrationHelper.UpdateAttributeQualifier("85422EA2-AC4E-44E5-99B9-30C131116734", "displaydescription", "True", "DA83FED2-1E06-44A7-8E40-AAECE75169D4"); // // keeping from old 5 // // Remove Batch Export Details Block from the Batch Details Page RockMigrationHelper.DeleteBlockAttributeValue("AB2F7C43-74F3-46A4-A005-F690D0A612D2", "DD9CD395-A4F0-4110-A349-C44EDFC0258B"); RockMigrationHelper.DeleteBlock("AB2F7C43-74F3-46A4-A005-F690D0A612D2"); // Remove the old export grid RockMigrationHelper.DeleteBlock("E209EFB6-DE18-4DD3-8B15-F7BE418C4955"); // Change the Attribute name, and grid display Sql(@" DECLARE @DateExportedAttributeId INT = (SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '4B6576DD-82F6-419F-8DF0-467D2636822D') IF @DateExportedAttributeId IS NOT NULL BEGIN UPDATE [Attribute] SET [Name] = 'Date Exported', [IsGridColumn] = 1 WHERE [Id] = @DateExportedAttributeId END "); // rename these attributes RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Debit Account", "", 3, "", "FD4EF8CC-DDB7-4DBD-9FD1-601A0119850B", "rocks.kfs.ShelbyFinancials.DebitAccount"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Revenue Department", "", 4, "", "2C1EE0CC-D329-453B-B4F0-29549E24ED05", "rocks.kfs.ShelbyFinancials.Department"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Revenue Account", "", 5, "", "0D114FB9-B1AA-4D6D-B0F3-9BB739710992", "rocks.kfs.ShelbyFinancials.CreditAccount"); // make sure the key gets updated properly because we're not sure if the old migration ran or not and can't UpdateEntityAttiribute until they're ensured RockMigrationHelper.EnsureAttributeByGuid("9B67459C-3C61-491D-B072-9A9830FBB18F", "rocks.kfs.ShelbyFinancials.Region", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("8B8D8BBF-B763-4314-87D2-00B9B8BA5A0F", "rocks.kfs.ShelbyFinancials.SuperFund", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("22699ECA-BB71-4EFD-B416-17B41ED3DBEC", "rocks.kfs.ShelbyFinancials.Location", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("CD925E61-F87D-461F-9EFA-C1E14397FC4D", "rocks.kfs.ShelbyFinancials.CostCenter", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); RockMigrationHelper.EnsureAttributeByGuid("65D935EC-3501-41A6-A2C5-CABC62AB9EF1", "rocks.kfs.ShelbyFinancials.AccountSub", Rock.SystemGuid.EntityType.FINANCIAL_ACCOUNT, Rock.SystemGuid.FieldType.TEXT, "", ""); // not all previous installs might have created these attributes. RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Region", "", 6, "", "9B67459C-3C61-491D-B072-9A9830FBB18F", "rocks.kfs.ShelbyFinancials.Region"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Super Fund", "", 7, "", "8B8D8BBF-B763-4314-87D2-00B9B8BA5A0F", "rocks.kfs.ShelbyFinancials.SuperFund"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Location", "", 8, "", "22699ECA-BB71-4EFD-B416-17B41ED3DBEC", "rocks.kfs.ShelbyFinancials.Location"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Cost Center", "", 9, "", "CD925E61-F87D-461F-9EFA-C1E14397FC4D", "rocks.kfs.ShelbyFinancials.CostCenter"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Account Sub", "", 10, "", "65D935EC-3501-41A6-A2C5-CABC62AB9EF1", "rocks.kfs.ShelbyFinancials.AccountSub"); // delete old namespace block types from database by guid RockMigrationHelper.DeleteBlock("00FC3A61-775D-4DE5-BC19-A1556FF465EA"); RockMigrationHelper.DeleteBlock("2DC7BB64-EBDB-4973-85A8-E2AF82F76256"); RockMigrationHelper.DeleteBlockType("235C370C-2CD7-4289-8B68-A8617F58B22B"); RockMigrationHelper.DeleteBlockType("B6F19C75-9B23-4EC5-810B-E05A5E11033F"); RockMigrationHelper.DeleteAttribute("CBC91780-4D02-47D5-B4AD-55AE2D5EBB49"); // Add new namespace blocks back RockMigrationHelper.UpdateBlockType("Shelby Financials Batch to Journal", "Block used to create Journal Entries in Shelby Financials from a Rock Financial Batch.", "~/Plugins/rocks_kfs/ShelbyFinancials/BatchToJournal.ascx", "KFS > Shelby Financials", "235C370C-2CD7-4289-8B68-A8617F58B22B"); RockMigrationHelper.AddBlock(Rock.SystemGuid.Page.FINANCIAL_BATCH_DETAIL, "", "235C370C-2CD7-4289-8B68-A8617F58B22B", "Shelby Financials Batch To Journal", "Main", "", "", 0, "00FC3A61-775D-4DE5-BC19-A1556FF465EA"); RockMigrationHelper.UpdateBlockType("Shelby Financials Batches to Journal", "Block used to create Journal Entries in Shelby Financials from multiple Rock Financial Batches.", "~/Plugins/rocks_kfs/ShelbyFinancials/BatchesToJournal.ascx", "KFS > Shelby Financials", "B6F19C75-9B23-4EC5-810B-E05A5E11033F"); RockMigrationHelper.UpdateBlockTypeAttribute("B6F19C75-9B23-4EC5-810B-E05A5E11033F", Rock.SystemGuid.FieldType.PAGE_REFERENCE, "Detail Page", "DetailPage", "", "", 0, Rock.SystemGuid.Page.FINANCIAL_BATCH_DETAIL, "CBC91780-4D02-47D5-B4AD-55AE2D5EBB49"); RockMigrationHelper.AddBlock(true, "3F123421-E5DE-474E-9F56-AAFCEDE115EF", "", "B6F19C75-9B23-4EC5-810B-E05A5E11033F", "Shelby Financials Batches To Journal", "Main", "", "", 0, "2DC7BB64-EBDB-4973-85A8-E2AF82F76256"); // // keeping from old 6 // RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "C19D547F-CD02-45C1-9962-FA1DBCEC2897"); // batch RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "DD221639-4EFF-4C16-9E7B-BE318E9E9F55"); // transaction RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "B097F23D-00D2-4216-916F-DA14335DA9CE"); // transaction detail RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "F8893830-B331-4C9F-AA4C-470F0C9B0D18"); // account Sql(@" DECLARE @AccountCategoryId int = ( SELECT TOP 1 [Id] FROM [Category] WHERE [Guid] = 'F8893830-B331-4C9F-AA4C-470F0C9B0D18' ) DECLARE @RegionAttributeId int = ( SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '9B67459C-3C61-491D-B072-9A9830FBB18F' ) DECLARE @SuperFundAttributeId int = ( SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '8B8D8BBF-B763-4314-87D2-00B9B8BA5A0F' ) DECLARE @LocationAttributeId int = ( SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '22699ECA-BB71-4EFD-B416-17B41ED3DBEC' ) DECLARE @CostCenterAttributeId int = ( SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = 'CD925E61-F87D-461F-9EFA-C1E14397FC4D' ) DECLARE @AccountSubAttributeId int = ( SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '65D935EC-3501-41A6-A2C5-CABC62AB9EF1' ) IF NOT EXISTS ( SELECT * FROM [AttributeCategory] WHERE [AttributeId] = @RegionAttributeId AND [CategoryId] = @AccountCategoryId ) BEGIN INSERT INTO [AttributeCategory] ( [AttributeId], [CategoryId] ) VALUES( @RegionAttributeId, @AccountCategoryId ) END IF NOT EXISTS ( SELECT * FROM [AttributeCategory] WHERE [AttributeId] = @SuperFundAttributeId AND [CategoryId] = @AccountCategoryId ) BEGIN INSERT INTO [AttributeCategory] ( [AttributeId], [CategoryId] ) VALUES( @SuperFundAttributeId, @AccountCategoryId ) END IF NOT EXISTS ( SELECT * FROM [AttributeCategory] WHERE [AttributeId] = @LocationAttributeId AND [CategoryId] = @AccountCategoryId ) BEGIN INSERT INTO [AttributeCategory] ( [AttributeId], [CategoryId] ) VALUES( @LocationAttributeId, @AccountCategoryId ) END IF NOT EXISTS ( SELECT * FROM [AttributeCategory] WHERE [AttributeId] = @CostCenterAttributeId AND [CategoryId] = @AccountCategoryId ) BEGIN INSERT INTO [AttributeCategory] ( [AttributeId], [CategoryId] ) VALUES( @CostCenterAttributeId, @AccountCategoryId ) END IF NOT EXISTS ( SELECT * FROM [AttributeCategory] WHERE [AttributeId] = @AccountSubAttributeId AND [CategoryId] = @AccountCategoryId ) BEGIN INSERT INTO [AttributeCategory] ( [AttributeId], [CategoryId] ) VALUES( @AccountSubAttributeId, @AccountCategoryId ) END "); // // keeping from old 7 // RockMigrationHelper.DeleteBlockType("1F50D804-67A0-4348-8DBB-7C1B46280025"); RockMigrationHelper.DeleteBlockType("6A8AAA9A-67BD-47CA-8FF7-400BDA9FEB2E"); RockMigrationHelper.DeleteAttribute("B72C0356-63AB-4E8B-8F43-40E994B94008"); } else { // block and page RockMigrationHelper.AddPage(true, Rock.SystemGuid.Page.FUNCTIONS_FINANCE, "D65F783D-87A9-4CC9-8110-E83466A0EADB", "Shelby GL Export", "", "3F123421-E5DE-474E-9F56-AAFCEDE115EF", "fa fa-archive", "EF65EFF2-99AC-4081-8E09-32A04518683A"); // project defined type RockMigrationHelper.AddDefinedType("Financial", "Financial Projects", "Used to designate what Project a Transaction should be associated with.", "2CE68D65-7EAC-4D5E-80B6-6FB903726961"); // batch export date RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialBatch", Rock.SystemGuid.FieldType.DATE_TIME, "", "", "Date Exported", "Date a batch was exported", 0, "", "4B6576DD-82F6-419F-8DF0-467D2636822D", "rocks.kfs.ShelbyFinancials.DateExported"); RockMigrationHelper.UpdateAttributeQualifier("4B6576DD-82F6-419F-8DF0-467D2636822D", "displayDiff", "False", "B76CAB38-B1C8-4D81-B1F5-521A0B507053"); RockMigrationHelper.UpdateAttributeQualifier("4B6576DD-82F6-419F-8DF0-467D2636822D", "format", "", "6AFC0F07-4706-4279-BDA4-204D57A4CC93"); // Change the grid display Sql(@" DECLARE @DateExportedAttributeId INT = (SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '4B6576DD-82F6-419F-8DF0-467D2636822D') IF @DateExportedAttributeId IS NOT NULL BEGIN UPDATE [Attribute] SET [IsGridColumn] = 1 WHERE [Id] = @DateExportedAttributeId END "); // transaction project RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialTransaction", Rock.SystemGuid.FieldType.DEFINED_VALUE, "", "", "Transaction Project", "Designates the Project at the Financial Transaction Level", 0, "", "365134A6-D516-48E0-AC67-A011D5D59D99", "rocks.kfs.ShelbyFinancials.Project"); RockMigrationHelper.UpdateAttributeQualifier("365134A6-D516-48E0-AC67-A011D5D59D99", "allowmultiple", "False", "B2205A7A-E11A-426C-9EF1-34CCD96F5047"); RockMigrationHelper.UpdateAttributeQualifier("365134A6-D516-48E0-AC67-A011D5D59D99", "definedtype", "", "E88DAEFC-BEAE-43CE-8A0E-DF96AFB95FC7"); RockMigrationHelper.UpdateAttributeQualifier("365134A6-D516-48E0-AC67-A011D5D59D99", "displaydescription", "True", "4287FEEF-4AB5-4F16-A872-546A393F2DB8"); // transaction detail project RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialTransactionDetail", Rock.SystemGuid.FieldType.DEFINED_VALUE, "", "", "Transaction Detail Project", "Designates the Project at the Financial Transaction Detail Level", 0, "", "951FAFFD-0513-4E31-9271-87853469E85E", "rocks.kfs.ShelbyFinancials.Project"); RockMigrationHelper.UpdateAttributeQualifier("951FAFFD-0513-4E31-9271-87853469E85E", "allowmultiple", "False", "BA61B518-C7B7-4F33-8E23-8D2109DA49CB"); RockMigrationHelper.UpdateAttributeQualifier("951FAFFD-0513-4E31-9271-87853469E85E", "definedtype", "", "408068EE-949F-41F5-8CC8-13C2DA6574FB"); RockMigrationHelper.UpdateAttributeQualifier("951FAFFD-0513-4E31-9271-87853469E85E", "displaydescription", "True", "A0679A5F-A76A-4408-9900-C576CC20E18F"); // account default project RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.DEFINED_VALUE, "", "", "Default Project", "Designates the Project at the Financial Account Level", 0, "", "85422EA2-AC4E-44E5-99B9-30C131116734", "rocks.kfs.ShelbyFinancials.Project"); RockMigrationHelper.UpdateAttributeQualifier("85422EA2-AC4E-44E5-99B9-30C131116734", "allowmultiple", "False", "7B25D6C9-7182-4617-A561-1A52F8140110"); RockMigrationHelper.UpdateAttributeQualifier("85422EA2-AC4E-44E5-99B9-30C131116734", "definedtype", "", "354F659B-06C1-4FEF-A88E-B9C0B1E64C08"); RockMigrationHelper.UpdateAttributeQualifier("85422EA2-AC4E-44E5-99B9-30C131116734", "displaydescription", "True", "DA83FED2-1E06-44A7-8E40-AAECE75169D4"); // set defined type qualifers Sql(@" DECLARE @ProjectDefinedTypeId int = ( SELECT TOP 1 [Id] FROM [DefinedType] WHERE [Guid] = '2CE68D65-7EAC-4D5E-80B6-6FB903726961' ) UPDATE [AttributeQualifier] SET [Value] = CAST( @ProjectDefinedTypeId AS varchar ) WHERE [Guid] = 'E88DAEFC-BEAE-43CE-8A0E-DF96AFB95FC7' UPDATE [AttributeQualifier] SET [Value] = CAST( @ProjectDefinedTypeId AS varchar ) WHERE [Guid] = '408068EE-949F-41F5-8CC8-13C2DA6574FB' UPDATE [AttributeQualifier] SET [Value] = CAST( @ProjectDefinedTypeId AS varchar ) WHERE [Guid] = '354F659B-06C1-4FEF-A88E-B9C0B1E64C08' "); // account gl attributes RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Company", "", 1, "", "A211D2C9-249D-4D33-B120-A3EAB37C1EDF", "rocks.kfs.ShelbyFinancials.Company"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Fund", "", 2, "", "B83D7934-F85A-42B7-AD0E-B4E16D63C189", "rocks.kfs.ShelbyFinancials.Fund"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Debit Account", "", 3, "", "FD4EF8CC-DDB7-4DBD-9FD1-601A0119850B", "rocks.kfs.ShelbyFinancials.DebitAccount"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Revenue Department", "", 4, "", "2C1EE0CC-D329-453B-B4F0-29549E24ED05", "rocks.kfs.ShelbyFinancials.Department"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Revenue Account", "", 5, "", "0D114FB9-B1AA-4D6D-B0F3-9BB739710992", "rocks.kfs.ShelbyFinancials.CreditAccount"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Region", "", 6, "", "9B67459C-3C61-491D-B072-9A9830FBB18F", "rocks.kfs.ShelbyFinancials.Region"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Super Fund", "", 7, "", "8B8D8BBF-B763-4314-87D2-00B9B8BA5A0F", "rocks.kfs.ShelbyFinancials.SuperFund"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Location", "", 8, "", "22699ECA-BB71-4EFD-B416-17B41ED3DBEC", "rocks.kfs.ShelbyFinancials.Location"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Cost Center", "", 9, "", "CD925E61-F87D-461F-9EFA-C1E14397FC4D", "rocks.kfs.ShelbyFinancials.CostCenter"); RockMigrationHelper.UpdateEntityAttribute("Rock.Model.FinancialAccount", Rock.SystemGuid.FieldType.TEXT, "", "", "Account Sub", "", 10, "", "65D935EC-3501-41A6-A2C5-CABC62AB9EF1", "rocks.kfs.ShelbyFinancials.AccountSub"); RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "C19D547F-CD02-45C1-9962-FA1DBCEC2897"); // batch RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "DD221639-4EFF-4C16-9E7B-BE318E9E9F55"); // transaction RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "B097F23D-00D2-4216-916F-DA14335DA9CE"); // transaction detail RockMigrationHelper.UpdateCategory("5997C8D3-8840-4591-99A5-552919F90CBD", "Shelby Financials Export", "fa fa-calculator", "", "F8893830-B331-4C9F-AA4C-470F0C9B0D18"); // account Sql(@" DECLARE @BatchEntityTypeId int = ( SELECT TOP 1 [Id] FROM [EntityType] WHERE [Guid] = 'BDD09C8E-2C52-4D08-9062-BE7D52D190C2' ) DECLARE @BatchCategoryId int = ( SELECT TOP 1 [Id] FROM [Category] WHERE [Guid] = 'C19D547F-CD02-45C1-9962-FA1DBCEC2897' ) UPDATE [Category] SET [EntityTypeQualifierColumn] = 'EntityTypeId', [EntityTypeQualifierValue] = @BatchEntityTypeId WHERE [Id] = @BatchCategoryId INSERT INTO [AttributeCategory] SELECT [Id], @BatchCategoryId FROM [Attribute] WHERE [Guid] = '4B6576DD-82F6-419F-8DF0-467D2636822D' DECLARE @TransactionEntityTypeId int = ( SELECT TOP 1 [Id] FROM [EntityType] WHERE [Guid] = '2C1CB26B-AB22-42D0-8164-AEDEE0DAE667' ) DECLARE @TransactionCategoryId int = ( SELECT TOP 1 [Id] FROM [Category] WHERE [Guid] = 'DD221639-4EFF-4C16-9E7B-BE318E9E9F55' ) UPDATE [Category] SET [EntityTypeQualifierColumn] = 'EntityTypeId', [EntityTypeQualifierValue] = @TransactionEntityTypeId WHERE [Id] = @TransactionCategoryId INSERT INTO [AttributeCategory] SELECT [Id], @TransactionCategoryId FROM [Attribute] WHERE [Guid] = '365134A6-D516-48E0-AC67-A011D5D59D99' DECLARE @TransactionDetailEntityTypeId int = ( SELECT TOP 1 [Id] FROM [EntityType] WHERE [Guid] = 'AC4AC28B-8E7E-4D7E-85DB-DFFB4F3ADCCE' ) DECLARE @TransactionDetailCategoryId int = ( SELECT TOP 1 [Id] FROM [Category] WHERE [Guid] = 'B097F23D-00D2-4216-916F-DA14335DA9CE' ) UPDATE [Category] SET [EntityTypeQualifierColumn] = 'EntityTypeId', [EntityTypeQualifierValue] = @TransactionDetailEntityTypeId WHERE [Id] = @TransactionDetailCategoryId INSERT INTO [AttributeCategory] SELECT [Id], @TransactionDetailCategoryId FROM [Attribute] WHERE [Guid] = '951FAFFD-0513-4E31-9271-87853469E85E' DECLARE @AccountEntityTypeId int = ( SELECT TOP 1 [Id] FROM [EntityType] WHERE [Guid] = '798BCE48-6AA7-4983-9214-F9BCEFB4521D' ) DECLARE @AccountCategoryId int = ( SELECT TOP 1 [Id] FROM [Category] WHERE [Guid] = 'F8893830-B331-4C9F-AA4C-470F0C9B0D18' ) UPDATE [Category] SET [EntityTypeQualifierColumn] = 'EntityTypeId', [EntityTypeQualifierValue] = @AccountEntityTypeId WHERE [Id] = @AccountCategoryId INSERT INTO [AttributeCategory] SELECT [Id], @AccountCategoryId FROM [Attribute] WHERE [Guid] = '85422EA2-AC4E-44E5-99B9-30C131116734' OR [Guid] = 'A211D2C9-249D-4D33-B120-A3EAB37C1EDF' OR [Guid] = 'B83D7934-F85A-42B7-AD0E-B4E16D63C189' OR [Guid] = 'FD4EF8CC-DDB7-4DBD-9FD1-601A0119850B' OR [Guid] = '2C1EE0CC-D329-453B-B4F0-29549E24ED05' OR [Guid] = '0D114FB9-B1AA-4D6D-B0F3-9BB739710992' OR [Guid] = '9B67459C-3C61-491D-B072-9A9830FBB18F' OR [Guid] = '8B8D8BBF-B763-4314-87D2-00B9B8BA5A0F' OR [Guid] = '22699ECA-BB71-4EFD-B416-17B41ED3DBEC' OR [Guid] = 'CD925E61-F87D-461F-9EFA-C1E14397FC4D' OR [Guid] = '65D935EC-3501-41A6-A2C5-CABC62AB9EF1' "); // create page for project defined type RockMigrationHelper.AddPage(true, Rock.SystemGuid.Page.ADMINISTRATION_FINANCE, "D65F783D-87A9-4CC9-8110-E83466A0EADB", "Projects", "", "01DAC445-9C4A-4469-9F39-A39549D75CBF", "fa fa-clipboard", "2B630A3B-E081-4204-A3E4-17BB3A5F063D"); // add defined value list block and set to projects defined type RockMigrationHelper.AddBlock(true, "01DAC445-9C4A-4469-9F39-A39549D75CBF", "", "0AB2D5E9-9272-47D5-90E4-4AA838D2D3EE", "Projects", "Main", "", "", 0, "23D1B7CE-D70C-4D81-B0D9-534A6D0542DC"); RockMigrationHelper.AddBlockAttributeValue(true, "23D1B7CE-D70C-4D81-B0D9-534A6D0542DC", "9280D61F-C4F3-4A3E-A9BB-BCD67FF78637", "2CE68D65-7EAC-4D5E-80B6-6FB903726961"); // add new blocks RockMigrationHelper.UpdateBlockType("Shelby Financials Batch to Journal", "Block used to create Journal Entries in Shelby Financials from a Rock Financial Batch.", "~/Plugins/rocks_kfs/ShelbyFinancials/BatchToJournal.ascx", "KFS > Shelby Financials", "235C370C-2CD7-4289-8B68-A8617F58B22B"); RockMigrationHelper.AddBlock(true, Rock.SystemGuid.Page.FINANCIAL_BATCH_DETAIL, "", "235C370C-2CD7-4289-8B68-A8617F58B22B", "Shelby Financial Batches To Journal", "Main", "", "", 0, "00FC3A61-775D-4DE5-BC19-A1556FF465EA"); // block type RockMigrationHelper.UpdateBlockType("Shelby Financials Batches to Journal", "Block used to create Journal Entries in Shelby Financials from multiple Rock Financial Batches.", "~/Plugins/rocks_kfs/ShelbyFinancials/BatchesToJournal.ascx", "KFS > Shelby Financials", "B6F19C75-9B23-4EC5-810B-E05A5E11033F"); RockMigrationHelper.AddBlockTypeAttribute("B6F19C75-9B23-4EC5-810B-E05A5E11033F", Rock.SystemGuid.FieldType.PAGE_REFERENCE, "Detail Page", "DetailPage", "", "", 0, Rock.SystemGuid.Page.FINANCIAL_BATCH_DETAIL, "CBC91780-4D02-47D5-B4AD-55AE2D5EBB49", true); // block on the Shelby batch export page RockMigrationHelper.AddBlock("3F123421-E5DE-474E-9F56-AAFCEDE115EF", "", "B6F19C75-9B23-4EC5-810B-E05A5E11033F", "Shelby Financials Batches To Journal", "Main", "", "", 0, "2DC7BB64-EBDB-4973-85A8-E2AF82F76256"); } }
/// <summary> /// Ups this instance. /// </summary> public override void Up() { // check if grouptype already exists using (var rockContext = new RockContext()) { var eventGuid = AdvancedEventGuid.AsGuid(); if (new GroupTypeService(rockContext).Queryable().Any(gt => gt.Name == "Advanced Event Registration" || gt.Guid.Equals(eventGuid))) { return; } } var migrateNamespace = false; var oldNamespace = "com.kfs.EventRegistration.Advanced"; // check if migration has previously run in case the grouptype check doesn't escape using (var rockContext = new RockContext()) { var migrationNumber = (System.Attribute.GetCustomAttribute(this.GetType(), typeof(MigrationNumberAttribute)) as MigrationNumberAttribute).Number; migrateNamespace = new PluginMigrationService(rockContext) .Queryable() .Where(m => m.PluginAssemblyName.Equals(oldNamespace, StringComparison.CurrentCultureIgnoreCase) && m.MigrationNumber == migrationNumber) .Any(); } // add primary grouptype RockMigrationHelper.AddGroupType("Advanced Event Registration", "This template triggers advanced features for the Event Registration module.", "Advanced Events", "Member", false, true, true, "fa fa-fire", 0, "", 0, "", AdvancedEventGuid, false); // add grouptype attributes to the primary grouptype AddGroupTypeAttribute("Rock.Model.GroupType", AdvancedEventGuid, BooleanFieldTypeGuid, "Allow Multiple Registrations", @"Should registrants be allowed to join multiple groups of this type?", 0, "False", true, "4F9CA590-882A-4A2A-9262-C9350953C996"); AddGroupTypeAttribute("Rock.Model.GroupType", AdvancedEventGuid, BooleanFieldTypeGuid, "Allow Volunteer Assignment", @"Should volunteers be allowed to join groups of this type?", 1, "False", true, "7129D352-5468-4BD9-BF2E-5CF9758D83BF"); AddGroupTypeAttribute("Rock.Model.GroupType", AdvancedEventGuid, BooleanFieldTypeGuid, "Show On Grid", @"Should the Registrants grid show assignment columns for this type?", 2, "False", true, "60BD7029-9D83-42CC-B904-9A1F3A89C1E6"); AddGroupTypeAttribute("Rock.Model.GroupType", AdvancedEventGuid, BooleanFieldTypeGuid, "Display Combined Memberships", @"Should the resource panel display a combined list of groups? If not, each group will be listed separately.", 3, "False", true, "7DD366B4-0A8C-4DA0-B14E-A17A1AFF55A6"); AddGroupTypeAttribute("Rock.Model.GroupType", AdvancedEventGuid, BooleanFieldTypeGuid, "Display Separate Roles", @"Should the resource panel display group members separately by role? If not, group members will be listed together.", 4, "False", true, "469BA2BC-FEB5-4C95-9BA2-B382F01C88E3"); // add child grouptypes RockMigrationHelper.AddGroupType("Event Activities", "Activity Groups for Advanced Events.", "Activity", "Participant", false, true, true, "fa fa-futbol-o", 0, AdvancedEventGuid, 0, "", EventActivityGuid, false); RockMigrationHelper.AddGroupType("Event Lodging", "Lodging Groups for Advanced Events.", "Lodging", "Occupant", false, true, true, "fa fa-bed", 0, AdvancedEventGuid, 0, "", EventLodgingGuid, false); RockMigrationHelper.AddGroupType("Event Transportation", "Transportation Groups for Advanced Events.", "Vehicle", "Passenger", false, true, true, "fa fa-bus", 0, AdvancedEventGuid, 0, "", EventTransportationGuid, false); RockMigrationHelper.AddGroupType("Event Volunteers", "Volunteer Groups for Advanced Events.", "Group", "Volunteer", false, true, true, "fa fa-handshake-o", 0, AdvancedEventGuid, 0, GroupTypePurposeServingAreaGuid, EventVolunteerGuid, false); // only add the association if this is the first time if (!migrateNamespace) { Sql($@" DECLARE @AdvancedEventId INT = (SELECT [ID] FROM GroupType WHERE [Guid] = '{AdvancedEventGuid}') INSERT GroupTypeAssociation (GroupTypeId, ChildGroupTypeId) VALUES (@AdvancedEventId, (SELECT [ID] FROM GroupType WHERE [Guid] = '{EventActivityGuid}')), (@AdvancedEventId, (SELECT [ID] FROM GroupType WHERE [Guid] = '{EventLodgingGuid}')), (@AdvancedEventId, (SELECT [ID] FROM GroupType WHERE [Guid] = '{EventTransportationGuid}')), (@AdvancedEventId, (SELECT [ID] FROM GroupType WHERE [Guid] = '{EventVolunteerGuid}')) "); } // add group roles RockMigrationHelper.AddGroupTypeRole(AdvancedEventGuid, "Member", "Member of Advanced Events (not used)", 0, null, null, Guid.NewGuid().ToString(), false, false, true); RockMigrationHelper.AddGroupTypeRole(EventActivityGuid, "Participant", "Participant role for Advanced Event Activity Groups", 0, null, null, Guid.NewGuid().ToString(), false, false, true); RockMigrationHelper.AddGroupTypeRole(EventLodgingGuid, "Leader", "Leader role for Advanced Event Lodging Groups", 0, null, null, Guid.NewGuid().ToString(), false, true, false); RockMigrationHelper.AddGroupTypeRole(EventLodgingGuid, "Occupant", "Occupant role for Advanced Event Lodging Groups", 0, null, null, Guid.NewGuid().ToString(), false, false, true); RockMigrationHelper.AddGroupTypeRole(EventTransportationGuid, "Driver", "Driver role for Advanced Event Transportation Groups", 0, null, null, Guid.NewGuid().ToString(), false, true, false); RockMigrationHelper.AddGroupTypeRole(EventTransportationGuid, "Passenger", "Passenger role for Advanced Event Transportation Groups", 0, null, null, Guid.NewGuid().ToString(), false, false, true); RockMigrationHelper.AddGroupTypeRole(EventVolunteerGuid, "Member", "Member role for Advanced Event Volunteer Groups", 0, null, null, Guid.NewGuid().ToString(), false, false, true); }
/// <summary> /// The commands to run to migrate plugin to the specific version /// </summary> public override void Up() { var migrateNamespace = false; var oldNamespace = "com.kfs.GroupRSVP"; // check if migration has previously run using (var rockContext = new RockContext()) { var migrationNumber = (System.Attribute.GetCustomAttribute(this.GetType(), typeof(MigrationNumberAttribute)) as MigrationNumberAttribute).Number; migrateNamespace = new PluginMigrationService(rockContext) .Queryable() .Where(m => m.PluginAssemblyName.Equals(oldNamespace, StringComparison.CurrentCultureIgnoreCase) && m.MigrationNumber == migrationNumber) .Any(); } if (migrateNamespace) { UpdateBlockTypeByGuid("RSVP Group Registration", "Allows a person to register for an RSVP Group.", "~/Plugins/rocks_kfs/RsvpGroups/RsvpGroupRegistration.ascx", "KFS > RSVP Groups", "F7B249C3-7FFD-483D-820F-A44D04E2BAB1"); UpdateBlockTypeByGuid("Group List Lava", "Lists groups for lava display.", "~/Plugins/rocks_kfs/Groups/GroupListLava.ascx", "KFS > Groups", "6731AF9D-F3CB-4CCB-AA42-19C9CB15CBF5"); // shared block type } else { // group type RockMigrationHelper.AddGroupType("RSVP Group", "A group that can be used to manage RSVP counts for the group members.", "Group", "Member", false, true, true, "fa fa-clipboard-list", 0, "", 0, "", "1A082EFF-30DA-44B2-8E48-02385C20828E", true); // group type role RockMigrationHelper.AddGroupTypeRole("1A082EFF-30DA-44B2-8E48-02385C20828E", "Member", "", 0, null, null, "60E0B95A-04D3-4839-917B-6BDAF9808EB5", true, false, true); // max rsvp RockMigrationHelper.AddGroupTypeGroupAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.INTEGER, "Max RSVP", "The RSVP limit for this group. '0' is unlimited.", 0, "", "AE34AFA5-8CB0-4BDA-8ACB-BAB661803BDC", true); // send email RockMigrationHelper.AddGroupTypeGroupAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.BOOLEAN, "Send Email", "Flag indicating if the group email should be sent when someone joins this group.", 1, "False", "9B67F3BF-5F7A-4A9E-A352-67F3D515F63A", true); // from email RockMigrationHelper.AddGroupTypeGroupAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.EMAIL, "From Email", "", 2, "", "6F8FB284-4CCB-45C1-A99E-F8ADA93856B1"); // from name RockMigrationHelper.AddGroupTypeGroupAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.TEXT, "From Name", "", 3, "", "9BBE3207-1939-45E3-8A26-6519045E8EA9"); RockMigrationHelper.AddAttributeQualifier("9BBE3207-1939-45E3-8A26-6519045E8EA9", "ispassword", "false", "8F791A08-72BC-482E-8FBC-8F6463C9669E"); // subject RockMigrationHelper.AddGroupTypeGroupAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.TEXT, "Subject", "", 4, "", "C0AD8B37-4D7F-4C17-9B4E-1E8D4352E22D"); RockMigrationHelper.AddAttributeQualifier("C0AD8B37-4D7F-4C17-9B4E-1E8D4352E22D", "ispassword", "false", "7284B714-AF12-440C-91FE-C4850F0D75F8"); // message RockMigrationHelper.AddGroupTypeGroupAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.HTML, "Message", "", 5, "", "7DCB5A58-1FD2-4261-9483-EA65A97151CD"); RockMigrationHelper.AddAttributeQualifier("7DCB5A58-1FD2-4261-9483-EA65A97151CD", "documentfolderroot", "", "B3C8C1C5-2DEB-49DA-87A8-8B87D48C9ED2"); RockMigrationHelper.AddAttributeQualifier("7DCB5A58-1FD2-4261-9483-EA65A97151CD", "imagefolderroot", "", "C5CA6A49-E7A7-45AA-B9F4-85F8F6FA8B5D"); RockMigrationHelper.AddAttributeQualifier("7DCB5A58-1FD2-4261-9483-EA65A97151CD", "toolbar", "Light", "242E3FFC-0680-494F-9EA3-55E8BEF11477"); RockMigrationHelper.AddAttributeQualifier("7DCB5A58-1FD2-4261-9483-EA65A97151CD", "userspecificroot", "False", "A59A34A7-0EA8-414C-A78F-034FFE954768"); // member rsvp RockMigrationHelper.AddGroupTypeGroupMemberAttribute("1A082EFF-30DA-44B2-8E48-02385C20828E", Rock.SystemGuid.FieldType.INTEGER, "RSVP Count", "", 0, "1", "877D17DD-6303-4863-B87C-F8D05111E835", true); // set member rsvp to display in grid, set the association to be self referenced, and set role to view Sql(@" DECLARE @GroupMemberRsvpCount INT = (SELECT TOP 1 [Id] FROM [Attribute] WHERE [Guid] = '877D17DD-6303-4863-B87C-F8D05111E835') UPDATE [Attribute] SET [IsGridColumn] = 1 WHERE [Id] = @GroupMemberRsvpCount DECLARE @RsvpGroupTypeId INT = (SELECT TOP 1 [Id] FROM [GroupType] WHERE [Guid] = '1A082EFF-30DA-44B2-8E48-02385C20828E') INSERT INTO [GroupTypeAssociation] ( [GroupTypeId], [ChildGroupTypeId] ) SELECT @RsvpGroupTypeId, @RsvpGroupTypeId UPDATE [GroupTypeRole] SET [CanView] = 1 WHERE [GroupTypeId] = @RsvpGroupTypeId "); // register blocks UpdateBlockTypeByGuid("RSVP Group Registration", "Allows a person to register for an RSVP Group.", "~/Plugins/rocks_kfs/RsvpGroups/RsvpGroupRegistration.ascx", "KFS > RSVP Groups", "F7B249C3-7FFD-483D-820F-A44D04E2BAB1"); UpdateBlockTypeByGuid("Group List Lava", "Lists groups for lava display.", "~/Plugins/rocks_kfs/Groups/GroupListLava.ascx", "KFS > Groups", "6731AF9D-F3CB-4CCB-AA42-19C9CB15CBF5"); // shared block type } }