Data access/service class for Rock.Model.BlockType objects.
Beispiel #1
0
        /// <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();
        }
Beispiel #2
0
        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();
            }
        }
Beispiel #3
0
        /// <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;
        }
        /// <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>
        /// Loads the block types.
        /// </summary>
        private void LoadBlockTypes(bool registerBlockTypes)
        {
            if (registerBlockTypes)
            {
                // Add any unregistered blocks
                try
                {
                    BlockTypeService.RegisterBlockTypes(Request.MapPath("~"), Page);
                }
                catch (Exception ex)
                {
                    nbMessage.Text    = "Error registering one or more block types";
                    nbMessage.Details = ex.Message + "<code>" + HttpUtility.HtmlEncode(ex.StackTrace) + "</code>";
                    nbMessage.Visible = true;
                }
            }

            // Load the block types
            using (var rockContext = new RockContext())
            {
                Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService(rockContext);
                var blockTypes = blockTypeService.Queryable().AsNoTracking()
                                 .Select(b => new { b.Id, b.Name, b.Category, b.Description })
                                 .ToList();

                ddlBlockType.Items.Clear();

                // Add the categorized block types
                foreach (var blockType in blockTypes
                         .Where(b => b.Category != "")
                         .OrderBy(b => b.Category)
                         .ThenBy(b => b.Name))
                {
                    var li = new ListItem(blockType.Name, blockType.Id.ToString());
                    li.Attributes.Add("optiongroup", blockType.Category);
                    li.Attributes.Add("title", blockType.Description);
                    ddlBlockType.Items.Add(li);
                }

                // Add the uncategorized block types
                foreach (var blockType in blockTypes
                         .Where(b => b.Category == null || b.Category == "")
                         .OrderBy(b => b.Name))
                {
                    var li = new ListItem(blockType.Name, blockType.Id.ToString());
                    li.Attributes.Add("optiongroup", "Other (not categorized)");
                    li.Attributes.Add("title", blockType.Description);
                    ddlBlockType.Items.Add(li);
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Loads the block types.
        /// </summary>
        private void LoadBlockTypes()
        {
            using (new Rock.Data.UnitOfWorkScope())
            {
                Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService();

                // Add any unregistered blocks
                blockTypeService.RegisterBlockTypes(Request.MapPath("~"), Page, CurrentPersonId);

                ddlBlockType.DataSource     = blockTypeService.Queryable().OrderBy(b => b.Name).ToList();
                ddlBlockType.DataTextField  = "Name";
                ddlBlockType.DataValueField = "Id";
                ddlBlockType.DataBind();
            }
        }
        /// <summary>
        /// Shows the edit.
        /// </summary>
        /// <param name="location">The location.</param>
        /// <param name="blockId">The block id.</param>
        protected void ShowEdit(BlockLocation location, int blockId)
        {
            using (var rockContext = new RockContext())
            {
                BlockService     blockService = new BlockService(rockContext);
                Rock.Model.Block block        = blockService.Get(blockId);
                hfBlockLocation.Value = location.ConvertToString();

                if (block != null)
                {
                    lAction.Text               = "Edit ";
                    hfBlockId.Value            = block.Id.ToString();
                    ddlBlockType.SelectedValue = block.BlockType.Id.ToString();
                    tbBlockName.Text           = block.Name;
                }
                else
                {
                    lAction.Text    = "Add ";
                    hfBlockId.Value = "0";

                    // Select HTML Content block by default
                    var blockType = new Rock.Model.BlockTypeService(rockContext)
                                    .GetByGuid(new Guid(Rock.SystemGuid.BlockType.HTML_CONTENT));
                    if (blockType != null)
                    {
                        ddlBlockType.SelectedValue = blockType.Id.ToString();
                    }
                    else
                    {
                        ddlBlockType.SelectedIndex = -1;
                    }

                    tbBlockName.Text = string.Empty;
                }
            }

            lAction.Text += hfBlockLocation.Value;

            pnlLists.Visible   = false;
            pnlDetails.Visible = true;
        }
        /// <summary>
        /// Handles the Delete event of the gBlockTypes control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param>
        protected void gBlockTypes_Delete( object sender, RowEventArgs e )
        {
            var rockContext = new RockContext();
            BlockTypeService blockTypeService = new BlockTypeService( rockContext );
            BlockType blockType = blockTypeService.Get( e.RowKeyId );
            if ( blockType != null )
            {
                string errorMessage;
                if ( !blockTypeService.CanDelete( blockType, out errorMessage ) )
                {
                    mdGridWarning.Show( errorMessage, ModalAlertType.Information );
                    return;
                }

                blockTypeService.Delete( blockType );
                rockContext.SaveChanges();
                Rock.Web.Cache.BlockTypeCache.Flush( blockType.Id );
            }

            BindGrid();
        }
Beispiel #9
0
        /// <summary>
        /// Loads the block types.
        /// </summary>
        private void LoadBlockTypes()
        {
            using (new Rock.Data.UnitOfWorkScope())
            {
                Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService();

                // Add any unregistered blocks
                blockTypeService.RegisterBlockTypes(Request.MapPath("~"), Page, CurrentPersonId);

                // Load the block types
                var blockTypes = blockTypeService.Queryable()
                                 .Select(b => new { b.Id, b.Name, b.Category, b.Description })
                                 .ToList();

                ddlBlockType.Items.Clear();

                // Add the categorized block types
                foreach (var blockType in blockTypes
                         .Where(b => b.Category != "")
                         .OrderBy(b => b.Category)
                         .ThenBy(b => b.Name))
                {
                    var li = new ListItem(blockType.Name, blockType.Id.ToString());
                    li.Attributes.Add("optiongroup", blockType.Category);
                    li.Attributes.Add("title", blockType.Description);
                    ddlBlockType.Items.Add(li);
                }

                // Add the uncategorized block types
                foreach (var blockType in blockTypes
                         .Where(b => b.Category == null || b.Category == "")
                         .OrderBy(b => b.Name))
                {
                    var li = new ListItem(blockType.Name, blockType.Id.ToString());
                    li.Attributes.Add("optiongroup", "Other (not categorized)");
                    li.Attributes.Add("title", blockType.Description);
                    ddlBlockType.Items.Add(li);
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="blockTypeId">The block type identifier.</param>
        public void ShowDetail( int blockTypeId )
        {
            pnlDetails.Visible = true;

            // Load depending on Add(0) or Edit
            BlockType blockType = null;

            if ( !blockTypeId.Equals( 0 ) )
            {
                blockType = new BlockTypeService( new RockContext() ).Get( blockTypeId );
                lActionTitle.Text = ActionTitle.Edit( BlockType.FriendlyTypeName ).FormatAsHtmlTitle();
                lPages.Visible = true;
                lblStatus.Visible = true;
                pdAuditDetails.SetEntity( blockType, ResolveRockUrl( "~" ) );
            }

            if (blockType == null)
            {
                blockType = new BlockType { Id = 0 };
                lActionTitle.Text = ActionTitle.Add( BlockType.FriendlyTypeName ).FormatAsHtmlTitle();
                lPages.Visible = false;
                lblStatus.Visible = false;
                // hide the panel drawer that show created and last modified dates
                pdAuditDetails.Visible = false;
            }

            hfBlockTypeId.Value = blockType.Id.ToString();
            tbName.Text = blockType.Name;
            tbPath.Text = blockType.Path;
            tbDescription.Text = blockType.Description;
            StringBuilder sb = new StringBuilder();
            foreach ( var fullPageName in blockType.Blocks.ToList().Where( a => a.Page != null ).Select(a => GetFullyQualifiedPageName(a.Page)).OrderBy(a => a))
            {
                sb.Append( fullPageName );
            }

            if ( sb.Length == 0 )
            {
                lPages.Text = "<span class='text-muted'><em>No pages are currently using this block</em></muted>";
            }
            else
            {
                lPages.Text = string.Format( "<ul>{0}</ul>", sb.ToString() );
            }

            string blockPath = Request.MapPath( blockType.Path );
            if ( !System.IO.File.Exists( blockPath ) )
            {
                lblStatus.Text = string.Format( "<span class='label label-danger'>The file '{0}' [{1}] does not exist.</span>", blockType.Path, blockType.Guid );
            }
            else
            {
                lblStatus.Text = "<span class='label label-success'>Block exists on the file system.</span>";
            }

            // render UI based on Authorized and IsSystem
            bool readOnly = false;

            nbEditModeMessage.Text = string.Empty;
            if ( !IsUserAuthorized( Authorization.EDIT ) )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( BlockType.FriendlyTypeName );
            }

            if ( blockType.IsSystem )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem( BlockType.FriendlyTypeName );
            }

            if ( readOnly )
            {
                lActionTitle.Text = ActionTitle.View( BlockType.FriendlyTypeName ).FormatAsHtmlTitle();
                btnCancel.Text = "Close";
            }

            tbName.ReadOnly = readOnly;
            tbPath.ReadOnly = readOnly;
            tbDescription.ReadOnly = readOnly;

            btnSave.Visible = !readOnly;
        }
        /// <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);
                    }
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Handles the Click event of the btnAddBlock 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 btnAddBlock_Click(object sender, EventArgs e)
        {
            tbNewBlockName.Text = string.Empty;

            // Load the block types
            using (var rockContext = new RockContext())
            {
                try
                {
                    BlockTypeService.RegisterBlockTypes(Request.MapPath("~"), Page);
                }
                catch
                {
                    // ignore
                }


                Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService(rockContext);
                var blockTypes = blockTypeService.Queryable().AsNoTracking()
                                 .Select(b => new { b.Id, b.Name, b.Category, b.Description })
                                 .ToList();

                ddlBlockType.Items.Clear();

                // Add the categorized block types
                foreach (var blockType in blockTypes
                         .Where(b => b.Category != string.Empty)
                         .OrderBy(b => b.Category)
                         .ThenBy(b => b.Name))
                {
                    var li = new ListItem(blockType.Name, blockType.Id.ToString());
                    li.Attributes.Add("optiongroup", blockType.Category);
                    li.Attributes.Add("title", blockType.Description);
                    ddlBlockType.Items.Add(li);
                }

                // Add the uncategorized block types
                foreach (var blockType in blockTypes
                         .Where(b => b.Category == null || b.Category == string.Empty)
                         .OrderBy(b => b.Name))
                {
                    var li = new ListItem(blockType.Name, blockType.Id.ToString());
                    li.Attributes.Add("optiongroup", "Other (not categorized)");
                    li.Attributes.Add("title", blockType.Description);
                    ddlBlockType.Items.Add(li);
                }
            }

            var htmlContentBlockType = BlockTypeCache.Read(Rock.SystemGuid.BlockType.HTML_CONTENT.AsGuid());

            ddlBlockType.SetValue(htmlContentBlockType.Id);

            rblAddBlockLocation.Items.Clear();

            var page = PageCache.Read(hfPageId.Value.AsInteger());

            var listItemPage = new ListItem();

            listItemPage.Text     = string.Format("Page ({0})", page.ToString());
            listItemPage.Value    = "Page";
            listItemPage.Selected = true;

            var listItemLayout = new ListItem();

            listItemLayout.Text     = string.Format("Layout ({0})", page.Layout);
            listItemLayout.Value    = "Layout";
            listItemLayout.Selected = false;

            var listItemSite = new ListItem();

            listItemSite.Text     = string.Format("Site ({0})", page.Layout.Site);
            listItemSite.Value    = "Site";
            listItemSite.Selected = false;

            rblAddBlockLocation.Items.Add(listItemPage);
            rblAddBlockLocation.Items.Add(listItemLayout);
            rblAddBlockLocation.Items.Add(listItemSite);
            mdAddBlock.Title = "Add Block to " + ddlZones.SelectedValue + " Zone";
            mdAddBlock.Show();
        }
Beispiel #14
0
        /// <summary>
        /// Shows the edit.
        /// </summary>
        /// <param name="blockTypeId">The block type id.</param>
        protected void ShowEdit( int blockTypeId )
        {
            pnlDetails.Visible = true;
            pnlList.Visible = false;

            BlockTypeService blockTypeService = new BlockTypeService();
            BlockType blockType = blockTypeService.Get( blockTypeId );

            if ( blockType != null )
            {
                lActionTitle.Text = ActionTitle.Edit( BlockType.FriendlyTypeName );
                hfBlockTypeId.Value = blockType.Id.ToString();
                tbName.Text = blockType.Name;
                tbPath.Text = blockType.Path;
                tbDescription.Text = blockType.Description;
            }
            else
            {
                lActionTitle.Text = ActionTitle.Add( BlockType.FriendlyTypeName );
                hfBlockTypeId.Value = 0.ToString();
                tbName.Text = string.Empty;
                tbPath.Text = string.Empty;
                tbDescription.Text = string.Empty;
            }
        }
Beispiel #15
0
        /// <summary>
        /// Loads the block types.
        /// </summary>
        private void LoadBlockTypes( bool registerBlockTypes )
        {
            if ( registerBlockTypes )
            {
                // Add any unregistered blocks
                try
                {
                    BlockTypeService.RegisterBlockTypes( Request.MapPath( "~" ), Page );
                }
                catch ( Exception ex )
                {
                    nbMessage.Text = "Error registering one or more block types";
                    nbMessage.Details = ex.Message + "<code>" + HttpUtility.HtmlEncode( ex.StackTrace ) + "</code>";
                    nbMessage.Visible = true;
                }
            }

            // Load the block types
            using ( var rockContext = new RockContext() )
            {
                Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService( rockContext );
                var blockTypes = blockTypeService.Queryable().AsNoTracking()
                    .Select( b => new { b.Id, b.Name, b.Category, b.Description } )
                    .ToList();

                ddlBlockType.Items.Clear();

                // Add the categorized block types
                foreach ( var blockType in blockTypes
                    .Where( b => b.Category != "" )
                    .OrderBy( b => b.Category )
                    .ThenBy( b => b.Name ) )
                {
                    var li = new ListItem( blockType.Name, blockType.Id.ToString() );
                    li.Attributes.Add( "optiongroup", blockType.Category );
                    li.Attributes.Add( "title", blockType.Description );
                    ddlBlockType.Items.Add( li );
                }

                // Add the uncategorized block types
                foreach ( var blockType in blockTypes
                    .Where( b => b.Category == null || b.Category == "" )
                    .OrderBy( b => b.Name ) )
                {
                    var li = new ListItem( blockType.Name, blockType.Id.ToString() );
                    li.Attributes.Add( "optiongroup", "Other (not categorized)" );
                    li.Attributes.Add( "title", blockType.Description );
                    ddlBlockType.Items.Add( li );
                }
            }
        }
        /// <summary>
        /// Loads the block types.
        /// </summary>
        private void LoadBlockTypes()
        {
            // Add any unregistered blocks
            BlockTypeService.RegisterBlockTypes( Request.MapPath( "~" ), Page );

            // Load the block types
            Rock.Model.BlockTypeService blockTypeService = new Rock.Model.BlockTypeService( new RockContext() );
            var blockTypes = blockTypeService.Queryable()
                .Select( b => new { b.Id, b.Name, b.Category, b.Description } )
                .ToList();

            ddlBlockType.Items.Clear();

            // Add the categorized block types
            foreach ( var blockType in blockTypes
                .Where( b => b.Category != "" )
                .OrderBy( b => b.Category )
                .ThenBy( b => b.Name ) )
            {
                var li = new ListItem( blockType.Name, blockType.Id.ToString() );
                li.Attributes.Add( "optiongroup", blockType.Category );
                li.Attributes.Add( "title", blockType.Description );
                ddlBlockType.Items.Add( li );
            }

            // Add the uncategorized block types
            foreach ( var blockType in blockTypes
                .Where( b => b.Category == null || b.Category == "" )
                .OrderBy( b => b.Name ) )
            {
                var li = new ListItem( blockType.Name, blockType.Id.ToString() );
                li.Attributes.Add( "optiongroup", "Other (not categorized)" );
                li.Attributes.Add( "title", blockType.Description );
                ddlBlockType.Items.Add( li );
            }
        }
Beispiel #17
0
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="itemKey">The item key.</param>
        /// <param name="itemKeyValue">The item key value.</param>
        public void ShowDetail( string itemKey, int itemKeyValue )
        {
            // return if unexpected itemKey 
            if ( itemKey != "blockTypeId" )
            {
                return;
            }

            pnlDetails.Visible = true;

            // Load depending on Add(0) or Edit
            BlockType blockType = null;
            if ( !itemKeyValue.Equals( 0 ) )
            {
                blockType = new BlockTypeService( new RockContext() ).Get( itemKeyValue );
                lActionTitle.Text = ActionTitle.Edit( BlockType.FriendlyTypeName ).FormatAsHtmlTitle();
                lstPages.Visible = true;
                lblStatus.Visible = true;
            }
            else
            {
                blockType = new BlockType { Id = 0 };
                lActionTitle.Text = ActionTitle.Add( BlockType.FriendlyTypeName ).FormatAsHtmlTitle();
                lstPages.Visible = false;
                lblStatus.Visible = false;
            }

            hfBlockTypeId.Value = blockType.Id.ToString();
            tbName.Text = blockType.Name;
            tbPath.Text = blockType.Path;
            tbDescription.Text = blockType.Description;
            foreach ( var fullPageName in blockType.Blocks.ToList().Where( a => a.Page != null ).Select(a => GetFullyQualifiedPageName(a.Page)).OrderBy(a => a))
            {
                lstPages.Items.Add( fullPageName );
            }

            if ( lstPages.Items.Count == 0 )
            {
                lstPages.Items.Add( "No pages are currently using this block" );
            }

            string blockPath = Request.MapPath( blockType.Path );
            if ( !System.IO.File.Exists( blockPath ) )
            {
                lblStatus.Text = string.Format( "<span class='label label-danger'>The file '{0}' [{1}] does not exist.</span>", blockType.Path, blockType.Guid );
            }
            else
            {
                lblStatus.Text = "<span class='label label-success'>Block exists on the file system.</span>";
            }

            // render UI based on Authorized and IsSystem
            bool readOnly = false;

            nbEditModeMessage.Text = string.Empty;
            if ( !IsUserAuthorized( Authorization.EDIT ) )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( BlockType.FriendlyTypeName );
            }

            if ( blockType.IsSystem )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem( BlockType.FriendlyTypeName );
            }

            if ( readOnly )
            {
                lActionTitle.Text = ActionTitle.View( BlockType.FriendlyTypeName ).FormatAsHtmlTitle();
                btnCancel.Text = "Close";
            }

            tbName.ReadOnly = readOnly;
            tbPath.ReadOnly = readOnly;
            tbDescription.ReadOnly = readOnly;

            btnSave.Visible = !readOnly;
        }
Beispiel #18
0
        /// <summary>
        /// Handles the Delete event of the gBlockTypes control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param>
        protected void gBlockTypes_Delete( object sender, RowEventArgs e )
        {
            BlockTypeService blockTypeService = new BlockTypeService();
            BlockType blockType = blockTypeService.Get( (int)gBlockTypes.DataKeys[e.RowIndex]["id"] );
            if ( CurrentBlock != null )
            {
                blockTypeService.Delete( blockType, CurrentPersonId );
                blockTypeService.Save( blockType, CurrentPersonId );

                Rock.Web.Cache.BlockTypeCache.Flush( blockType.Id );
            }

            BindGrid();
        }
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            BlockTypeService blockTypeService = new BlockTypeService( new RockContext() );
            SortProperty sortProperty = gBlockTypes.SortProperty;

            var blockTypes = blockTypeService.Queryable();

            // Exclude system blocks if checked.
            if ( !string.IsNullOrWhiteSpace( gfSettings.GetUserPreference("Exclude System") ) )
            {
                blockTypes = blockTypes.Where( b => b.IsSystem == false );
            }

            // Filter by Name
            string nameFilter = gfSettings.GetUserPreference( "Name" );
            if ( !string.IsNullOrEmpty( nameFilter.Trim() ) )
            {
                blockTypes = blockTypes.Where( b => b.Name.Contains( nameFilter.Trim() ) );
            }

            // Filter by Path
            string path = gfSettings.GetUserPreference( "Path" );
            if ( !string.IsNullOrEmpty( path.Trim() ) )
            {
                blockTypes = blockTypes.Where( b => b.Path.Contains( path.Trim() ) );
            }

            string category = gfSettings.GetUserPreference( "Category" );
            if (!string.IsNullOrWhiteSpace(category))
            {
                blockTypes = blockTypes.Where( b => b.Category == category );
            }

            var selectQry = blockTypes.Select( a =>
                new
                {
                    a.Id,
                    a.Name,
                    a.Category,
                    a.Description,
                    a.Path,
                    BlocksCount = a.Blocks.Count(),
                    a.IsSystem
                } );

            if ( sortProperty != null )
            {
                if ( sortProperty.Property == "Status" )
                {
                    // special case:  See if the file exists and sort by that
                    if ( sortProperty.Direction == System.Web.UI.WebControls.SortDirection.Ascending )
                    {
                        gBlockTypes.DataSource = selectQry.ToList().OrderBy( a => System.IO.File.Exists( Request.MapPath( a.Path ) ) ).ToList();
                    }
                    else
                    {
                        gBlockTypes.DataSource = selectQry.ToList().OrderBy( a => !System.IO.File.Exists( Request.MapPath( a.Path ) ) ).ToList();
                    }
                }
                else
                {
                    gBlockTypes.DataSource = selectQry.Sort( sortProperty ).ToList();
                }
            }
            else
            {
                gBlockTypes.DataSource = selectQry.OrderBy( b => b.Name ).ToList();
            }

            gBlockTypes.DataBind();
        }
Beispiel #20
0
        /// <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
                {
                    //
                }
            }
        }
Beispiel #21
0
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            BlockTypeService blockTypeService = new BlockTypeService();
            SortProperty sortProperty = gBlockTypes.SortProperty;

            if ( sortProperty != null )
            {
                gBlockTypes.DataSource = blockTypeService.Queryable().Sort( sortProperty ).ToList();
            }
            else
            {
                gBlockTypes.DataSource = blockTypeService.Queryable().OrderBy( b => b.Name ).ToList();
            }

            gBlockTypes.DataBind();
        }
Beispiel #22
0
        /// <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();
        
        }
Beispiel #23
0
        /// <summary>
        /// Shows the edit.
        /// </summary>
        /// <param name="location">The location.</param>
        /// <param name="blockId">The block id.</param>
        protected void ShowEdit( BlockLocation location, int blockId )
        {
            using ( var rockContext = new RockContext() )
            {
                BlockService blockService = new BlockService( rockContext );
                Rock.Model.Block block = blockService.Get( blockId );
                hfBlockLocation.Value = location.ConvertToString();

                if ( block != null )
                {
                    lAction.Text = "Edit ";
                    hfBlockId.Value = block.Id.ToString();
                    ddlBlockType.SelectedValue = block.BlockType.Id.ToString();
                    tbBlockName.Text = block.Name;
                }
                else
                {
                    lAction.Text = "Add ";
                    hfBlockId.Value = "0";

                    // Select HTML Content block by default
                    var blockType = new Rock.Model.BlockTypeService( rockContext )
                        .GetByGuid( new Guid( Rock.SystemGuid.BlockType.HTML_CONTENT ) );
                    if ( blockType != null )
                    {
                        ddlBlockType.SelectedValue = blockType.Id.ToString();
                    }
                    else
                    {
                        ddlBlockType.SelectedIndex = -1;
                    }

                    tbBlockName.Text = string.Empty;
                }
            }

            lAction.Text += hfBlockLocation.Value;

            pnlLists.Visible = false;
            pnlDetails.Visible = true;
        }
        /// <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();
        }
Beispiel #25
0
        /// <summary>
        /// Handles the Delete event of the gBlockTypes control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param>
        protected void gBlockTypes_Delete( object sender, RowEventArgs e )
        {
            RockTransactionScope.WrapTransaction( () =>
            {
                BlockTypeService blockTypeService = new BlockTypeService();
                BlockType blockType = blockTypeService.Get( (int)e.RowKeyValue );
                if ( blockType != null )
                {
                    string errorMessage;
                    if ( !blockTypeService.CanDelete( blockType, out errorMessage ) )
                    {
                        mdGridWarning.Show( errorMessage, ModalAlertType.Information );
                        return;
                    }

                    blockTypeService.Delete( blockType, CurrentPersonId );
                    blockTypeService.Save( blockType, CurrentPersonId );
                    Rock.Web.Cache.BlockTypeCache.Flush( blockType.Id );
                }
            } );

            BindGrid();
        }
Beispiel #26
0
        /// <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;
        }
Beispiel #27
0
        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();
            }
        }
Beispiel #28
0
        /// <summary>
        /// Expands the files.
        /// </summary>
        /// <param name="packageFiles">The package files.</param>
        private void ExpandFiles( IEnumerable<IPackageFile> packageFiles )
        {
            // Remove export.json file from the list of files to be unzipped
            var filesToUnzip = packageFiles.Where( f => !f.Path.Contains( "export.json" ) ).ToList();
            var blockTypeService = new BlockTypeService();
            var installedBlockTypes = blockTypeService.Queryable();
            var webRoot = HttpContext.Current.Server.MapPath( "~" );

            // Compare the packages files with currently installed block types, removing anything that already exists
            foreach ( var blockType in installedBlockTypes )
            {
                var blockFileName = blockType.Path.Substring( blockType.Path.LastIndexOf( "/", StringComparison.InvariantCultureIgnoreCase ) );
                blockFileName = blockFileName.Replace( '/', Path.DirectorySeparatorChar );
                filesToUnzip.RemoveAll( f => f.Path.Contains( blockFileName ) );
            }

            foreach ( var packageFile in filesToUnzip )
            {
                var path = Path.Combine( webRoot, packageFile.EffectivePath );
                var file = new FileInfo( path );

                // Err on the side of not being destructive for now. Consider refactoring to give user a choice
                // on whether or not to overwrite these files.
                if ( file.Exists )
                {
                    WarningMessages.Add( string.Format( "Skipping '{0}', found duplicate file at '{1}'.", file.Name, path ) );
                    continue;
                }
                
                // Write each file out to disk
                using ( var fileStream = new FileStream( path, FileMode.Create ) )
                {
                    var stream = packageFile.GetStream();
                    var bytes = stream.ReadAllBytes();
                    fileStream.Write( bytes, 0, bytes.Length );
                    stream.Close();
                }
            }
        }