/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { BlockType blockType; BlockTypeService blockTypeService = new BlockTypeService(); int blockTypeId = int.Parse( hfBlockTypeId.Value ); if ( blockTypeId == 0 ) { blockType = new BlockType(); blockTypeService.Add( blockType, CurrentPersonId ); } else { BlockTypeCache.Flush( blockTypeId ); blockType = blockTypeService.Get( blockTypeId ); } blockType.Name = tbName.Text; blockType.Path = tbPath.Text; blockType.Description = tbDescription.Text; if ( !blockType.IsValid ) { // Controls will render the error messages return; } blockTypeService.Save( blockType, CurrentPersonId ); BindGrid(); pnlDetails.Visible = false; pnlList.Visible = true; }
private void LoadBlockTypes() { using (new Rock.Data.UnitOfWorkScope()) { Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService(); // Add any unregistered blocks foreach (Rock.Model.BlockType blockType in blockTypeService.GetUnregisteredBlocks(Request.MapPath("~"))) { try { Control control = LoadControl(blockType.Path); if (control is Rock.Web.UI.RockBlock) { blockType.Name = Path.GetFileNameWithoutExtension(blockType.Path); // Split the name on intercapped changes (ie, "HelloWorld" becomes "Hello World") blockType.Name = System.Text.RegularExpressions.Regex.Replace(blockType.Name, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 "); blockType.Description = blockType.Path; blockTypeService.Add(blockType, CurrentPersonId); blockTypeService.Save(blockType, CurrentPersonId); } } catch { } } ddlBlockType.DataSource = blockTypeService.Queryable().OrderBy(b => b.Name).ToList(); ddlBlockType.DataTextField = "Name"; ddlBlockType.DataValueField = "Id"; ddlBlockType.DataBind(); } }
/// <summary> /// Registers any block types that are not currently registered in Rock. /// </summary> /// <param name="physWebAppPath">A <see cref="System.String" /> containing the physical path to Rock on the server.</param> /// <param name="page">The <see cref="System.Web.UI.Page" />.</param> /// <param name="refreshAll">if set to <c>true</c> will refresh name, category, and description for all block types (not just the new ones)</param> public static void RegisterBlockTypes( string physWebAppPath, System.Web.UI.Page page, bool refreshAll = false) { // Dictionary for block types. Key is path, value is friendly name var list = new Dictionary<string, string>(); // Find all the blocks in the Blocks folder... FindAllBlocksInPath( physWebAppPath, list, "Blocks" ); // Now do the exact same thing for the Plugins folder... FindAllBlocksInPath( physWebAppPath, list, "Plugins" ); // Get a list of the BlockTypes already registered (via the path) var rockContext = new RockContext(); var blockTypeService = new BlockTypeService( rockContext ); var registered = blockTypeService.Queryable().ToList(); // for each BlockType foreach ( string path in list.Keys) { if ( refreshAll || !registered.Any( b => b.Path.Equals( path, StringComparison.OrdinalIgnoreCase ) ) ) { // Attempt to load the control try { System.Web.UI.Control control = page.LoadControl( path ); if ( control is Rock.Web.UI.RockBlock ) { var blockType = registered.FirstOrDefault( b => b.Path.Equals( path, StringComparison.OrdinalIgnoreCase ) ); if ( blockType == null ) { // Create new BlockType record and save it blockType = new BlockType(); blockType.Path = path; blockTypeService.Add( blockType ); } Type controlType = control.GetType(); // Update Name, Category, and Description based on block's attribute definitions blockType.Name = Rock.Reflection.GetDisplayName( controlType ) ?? string.Empty; if ( string.IsNullOrWhiteSpace( blockType.Name ) ) { // Parse the relative path to get the name var nameParts = list[path].Split( '/' ); for ( int i = 0; i < nameParts.Length; i++ ) { if ( i == nameParts.Length - 1 ) { nameParts[i] = Path.GetFileNameWithoutExtension( nameParts[i] ); } nameParts[i] = nameParts[i].SplitCase(); } blockType.Name = string.Join( " > ", nameParts ); } if ( blockType.Name.Length > 100 ) { blockType.Name = blockType.Name.Truncate( 100 ); } blockType.Category = Rock.Reflection.GetCategory( controlType ) ?? string.Empty; blockType.Description = Rock.Reflection.GetDescription( controlType ) ?? string.Empty; } } catch ( Exception ex ) { ExceptionLogService.LogException( new Exception( string.Format("Problem processing block with path '{0}'.", path ), ex ), null ); } } } rockContext.SaveChanges(); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { BlockType blockType; var rockContext = new RockContext(); BlockTypeService blockTypeService = new BlockTypeService( rockContext ); int blockTypeId = int.Parse( hfBlockTypeId.Value ); if ( blockTypeId == 0 ) { blockType = new BlockType(); blockTypeService.Add( blockType ); } else { BlockTypeCache.Flush( blockTypeId ); blockType = blockTypeService.Get( blockTypeId ); } blockType.Name = tbName.Text; blockType.Path = tbPath.Text; blockType.Description = tbDescription.Text; if ( !blockType.IsValid ) { // Controls will render the error messages return; } rockContext.SaveChanges(); NavigateToParentPage(); }
/// <summary> /// Registers any block types that are not currently registered in Rock. /// </summary> /// <param name="physWebAppPath">A <see cref="System.String" /> containing the physical path to Rock on the server.</param> /// <param name="page">The <see cref="System.Web.UI.Page" />.</param> /// <param name="refreshAll">if set to <c>true</c> will refresh name, category, and description for all block types (not just the new ones)</param> public static void RegisterBlockTypes(string physWebAppPath, System.Web.UI.Page page, bool refreshAll = false) { // Dictionary for block types. Key is path, value is friendly name var list = new Dictionary <string, string>(); RegisterEntityBlockTypes(refreshAll); // Find all the blocks in the Blocks folder... FindAllBlocksInPath(physWebAppPath, list, "Blocks"); // Now do the exact same thing for the Plugins folder... FindAllBlocksInPath(physWebAppPath, list, "Plugins"); // Get a list of the BlockTypes already registered (via the path) List <string> registeredPaths; if (refreshAll) { FlushRegistrationCache(); registeredPaths = new List <string>(); } else { using (var rockContext = new RockContext()) { registeredPaths = new BlockTypeService(rockContext) .Queryable().AsNoTracking() .Where(b => !string.IsNullOrEmpty(b.Path)) .Select(b => b.Path) .ToList(); } } // Get the Block Entity Type int?blockEntityTypeId = EntityTypeCache.Get(typeof(Block)).Id; // for each BlockType foreach (string path in list.Keys) { // If the block has been previously processed or successfully registered, ignore it. if (_processedBlockPaths.Any(b => b.Equals(path, StringComparison.OrdinalIgnoreCase)) || registeredPaths.Any(b => b.Equals(path, StringComparison.OrdinalIgnoreCase))) { continue; } // Store the block path in the list of processed blocks to avoid re-processing if the registration fails. lock ( _processedBlockPathsLock ) { _processedBlockPaths.Add(path); } // Attempt to load the control try { var blockCompiledType = System.Web.Compilation.BuildManager.GetCompiledType(path); if (blockCompiledType != null && typeof(Web.UI.RockBlock).IsAssignableFrom(blockCompiledType)) { using (var rockContext = new RockContext()) { var blockTypeService = new BlockTypeService(rockContext); var blockType = blockTypeService.Queryable() .FirstOrDefault(b => b.Path == path); if (blockType == null) { // Create new BlockType record and save it blockType = new BlockType(); blockType.Path = path; blockTypeService.Add(blockType); } Type controlType = blockCompiledType; // Update Name, Category, and Description based on block's attribute definitions blockType.Name = Reflection.GetDisplayName(controlType) ?? string.Empty; if (string.IsNullOrWhiteSpace(blockType.Name)) { // Parse the relative path to get the name var nameParts = list[path].Split('/'); for (int i = 0; i < nameParts.Length; i++) { if (i == nameParts.Length - 1) { nameParts[i] = Path.GetFileNameWithoutExtension(nameParts[i]); } nameParts[i] = nameParts[i].SplitCase(); } blockType.Name = string.Join(" > ", nameParts); } if (blockType.Name.Length > 100) { blockType.Name = blockType.Name.Truncate(100); } blockType.Category = Rock.Reflection.GetCategory(controlType) ?? string.Empty; blockType.Description = Rock.Reflection.GetDescription(controlType) ?? string.Empty; rockContext.SaveChanges(); // Update the attributes used by the block Rock.Attribute.Helper.UpdateAttributes(controlType, blockEntityTypeId, "BlockTypeId", blockType.Id.ToString(), rockContext); } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"RegisterBlockTypes failed for {path} with exception: {ex.Message}"); ExceptionLogService.LogException(new Exception(string.Format("Problem processing block with path '{0}'.", path), ex), null); } } }
/// <summary> /// Registers any entity-based block types that are not currently registered in Rock. /// </summary> /// <param name="refreshAll">if set to <c>true</c> will refresh name, category, and description for all block types (not just the new ones)</param> private static void RegisterEntityBlockTypes(bool refreshAll = false) { var rockBlockTypes = Reflection.FindTypes(typeof(Blocks.IRockBlockType)); List <Type> registeredTypes; using (var rockContext = new RockContext()) { registeredTypes = new BlockTypeService(rockContext) .Queryable().AsNoTracking() .Where(b => b.EntityTypeId.HasValue && !string.IsNullOrEmpty(b.EntityType.AssemblyName)) .ToList() .Select(b => Type.GetType(b.EntityType.AssemblyName, false)) .Where(b => b != null) .ToList(); } // Get the Block Entity Type int?blockEntityTypeId = EntityTypeCache.Get(typeof(Block)).Id; // for each BlockType foreach (var type in rockBlockTypes.Values) { if (refreshAll || !registeredTypes.Any(t => t == type)) { // Attempt to load the control try { using (var rockContext = new RockContext()) { var entityTypeId = EntityTypeCache.Get(type, true, rockContext).Id; var blockTypeService = new BlockTypeService(rockContext); var blockType = blockTypeService.Queryable() .FirstOrDefault(b => b.EntityTypeId == entityTypeId); if (blockType == null) { // Create new BlockType record and save it blockType = new BlockType(); blockType.EntityTypeId = entityTypeId; blockTypeService.Add(blockType); } // Update Name, Category, and Description based on block's attribute definitions blockType.Name = Reflection.GetDisplayName(type) ?? string.Empty; if (string.IsNullOrWhiteSpace(blockType.Name)) { blockType.Name = type.FullName; } if (blockType.Name.Length > 100) { blockType.Name = blockType.Name.Truncate(100); } blockType.Category = Rock.Reflection.GetCategory(type) ?? string.Empty; blockType.Description = Rock.Reflection.GetDescription(type) ?? string.Empty; rockContext.SaveChanges(); // Update the attributes used by the block Rock.Attribute.Helper.UpdateAttributes(type, blockEntityTypeId, "BlockTypeId", blockType.Id.ToString(), rockContext); } } catch (Exception ex) { Debug.WriteLine($"RegisterEntityBlockTypes failed for {type.FullName} with exception: {ex.Message}"); ExceptionLogService.LogException(new Exception(string.Format("Problem processing block with path '{0}'.", type.FullName), ex), null); } } } }
/// <summary> /// Imports the page. /// </summary> /// <param name="uploadedPackage">Byte array of the uploaded package</param> /// <param name="fileName">File name of uploaded package</param> /// <param name="personId">Id of the Person performing the import</param> /// <param name="pageId">The Id of the Page to save new data underneath</param> /// <param name="siteId">The Id of the Site tha the Page is being imported into</param> public bool ImportPage( byte[] uploadedPackage, string fileName, int personId, int pageId, int siteId ) { // Write .nupkg file to the PackageStaging folder... var path = Path.Combine( HttpContext.Current.Server.MapPath( "~/App_Data/PackageStaging" ), fileName ); using ( var file = new FileStream( path, FileMode.Create ) ) { file.Write( uploadedPackage, 0, uploadedPackage.Length ); } var package = new ZipPackage( path ); var packageFiles = package.GetFiles().ToList(); var exportFile = packageFiles.FirstOrDefault( f => f.Path.Contains( "export.json" ) ); Page page = null; // If export.json is present, deserialize data // * Are there any new BlockTypes to register? If so, save them first. // * Scrub out any `Id` and `Guid` fields that came over from export // * Save page data via PageService if ( exportFile != null ) { string json; using ( var stream = exportFile.GetStream() ) { json = stream.ReadToEnd(); } page = Page.FromJson( json ); } // Validate package... // + Does it have any executable .dll files? Should those go to the bin folder, or into a plugins directory to be loaded via MEF? // - Does it have code or asset files that need to go on the file system? (Done) // - Does it have an export.json file? Should that be a requirement? (Done) // + Does it have any corresponding SQL, migrations, seed methods to run, etc. if ( page != null ) { // Find new block types and save them prior to scrubbing data... var newBlockTypes = FindNewBlockTypes( page, new BlockTypeService().Queryable() ).ToList(); RockTransactionScope.WrapTransaction( () => { try { var blockTypeService = new BlockTypeService(); foreach ( var blockType in newBlockTypes ) { blockTypeService.Add( blockType, personId ); blockTypeService.Save( blockType, personId ); } ValidateImportData( page, newBlockTypes ); SavePages( page, newBlockTypes, personId, pageId, siteId ); ExpandFiles( packageFiles ); } catch ( Exception e ) { ErrorMessages.Add( e.Message ); } }); // Clean up PackageStaging folder on successful import. var file = new FileInfo( path ); file.Delete(); return ErrorMessages.Count <= 0; } ErrorMessages.Add( "The export package uploaded does not appear to have any data associated with it." ); return false; }
/// <summary> /// Scans for unregistered blocks. /// </summary> private void ScanForUnregisteredBlocks() { BlockTypeService blockTypeService = new BlockTypeService(); foreach ( Rock.Model.BlockType blockType in blockTypeService.GetUnregisteredBlocks( Request.MapPath( "~" ) ) ) { try { Control control = LoadControl( blockType.Path ); if ( control is Rock.Web.UI.RockBlock ) { blockType.Name = Path.GetFileNameWithoutExtension( blockType.Path ).SplitCase(); blockType.Description = Rock.Reflection.GetDescription( control.GetType() ) ?? string.Empty; blockTypeService.Add( blockType, CurrentPersonId ); blockTypeService.Save( blockType, CurrentPersonId ); } } catch { // } } }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { BlockType blockType; BlockTypeService blockTypeService = new BlockTypeService(); int blockTypeId = int.Parse( hfBlockTypeId.Value ); if ( blockTypeId == 0 ) { blockType = new BlockType(); blockTypeService.Add( blockType, CurrentPersonId ); } else { BlockTypeCache.Flush( blockTypeId ); blockType = blockTypeService.Get( blockTypeId ); } blockType.Name = tbName.Text; blockType.Path = tbPath.Text; blockType.Description = tbDescription.Text; if ( !blockType.IsValid ) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction( () => { blockTypeService.Save( blockType, CurrentPersonId ); } ); NavigateToParentPage(); }
private void LoadBlockTypes() { using ( new Rock.Data.UnitOfWorkScope() ) { Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService(); // Add any unregistered blocks foreach ( Rock.Model.BlockType blockType in blockTypeService.GetUnregisteredBlocks( Request.MapPath( "~" ) ) ) { try { Control control = LoadControl( blockType.Path ); if ( control is Rock.Web.UI.RockBlock ) { blockType.Name = Path.GetFileNameWithoutExtension( blockType.Path ); // Split the name on intercapped changes (ie, "HelloWorld" becomes "Hello World") blockType.Name = System.Text.RegularExpressions.Regex.Replace( blockType.Name, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 " ); blockType.Description = blockType.Path; blockTypeService.Add( blockType, CurrentPersonId ); blockTypeService.Save( blockType, CurrentPersonId ); } } catch { } } ddlBlockType.DataSource = blockTypeService.Queryable().OrderBy( b => b.Name).ToList(); ddlBlockType.DataTextField = "Name"; ddlBlockType.DataValueField = "Id"; ddlBlockType.DataBind(); } }