Backing up Document Types
This is obviously a bit of a problem since they are actually stored in the database, not on the file system. Hmmm…
Then yesterday I was talking to Tatham Oddie about it and how you could go about CI with Umbraco. Then after bouncing a few ideas of Shannon we had a great idea, that when you say a DocumentType it would just dump it to the file system. You can then check this file into your source control system and you have a backup.
Sounds pretty simple, and in fact, Umbraco has all the stuff you’d need for this, it’s just a matter of doing it. So while waiting for a rather large project to check out of source control I decided to just write it.
Please note, the following code is not tested, it’s just a POC, when I get some time I do plan on actually testing it :P
How do go about it
It’s actually quite simple, you just need to tie into the Umbraco event model for a DocumentType and use the built in XML export feature.
I’ve also done the code so you can either dump to a single file or to multiple files (depending which is easiest in your solution.
It doesn’t check the files out for you, so if you’re using something like TFS you’ll have a problem, but I have put in handlers for read-only files.
Also, there’s no error checking, like I said, this is POC code :P.
Code baby!
using System.Linq; using System.IO; using System.Web; using System.Xml.Linq; using umbraco; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.web; namespace AaronPowell.Umbraco { public class DocumentTypeSerializer : ApplicationBase { public DocumentTypeSerializer() { DocumentType.AfterSave += new DocumentType.SaveEventHandler(DocumentType_AfterSave); DocumentType.AfterDelete += new DocumentType.DeleteEventHandler(DocumentType_AfterDelete); } void DocumentType_AfterDelete(DocumentType sender, umbraco.cms.businesslogic.DeleteEventArgs e) { DumpDocumentTypes(false); } void DocumentType_AfterSave(DocumentType sender, umbraco.cms.businesslogic.SaveEventArgs e) { DumpDocumentTypes(false); } private static void DumpDocumentTypes(bool useSingleFile) { var allDocTypes = DocumentType.GetAllAsList(); var storageFolder = GlobalSettings.StorageDirectory + "/"; System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument(); if(useSingleFile) { var xdoc = new XDocument(new XElement("DocumentTypes")); foreach (var dt in allDocTypes) xdoc.Root.Add(XElement.Parse(dt.ToXml(xmlDoc).InnerXml)); var file = storageFolder + "DocumentTypes.config"; var fileOnFileSystem = new FileInfo(HttpContext.Current.Server.MapPath(file)); if (fileOnFileSystem.Exists) { if (fileOnFileSystem.Attributes == FileAttributes.ReadOnly) fileOnFileSystem.Attributes &= ~FileAttributes.ReadOnly; fileOnFileSystem.Delete(); } xdoc.Save(fileOnFileSystem.FullName); } else { storageFolder += "DocumentTypes/"; if(!Directory.Exists(storageFolder)) { Directory.Create(storageFolder); } else { var di = new DirectoryInfo(storageFolder); var files = di.GetFiles(); foreach(var file in files) { if (file.Exists) { if (file.Attributes == FileAttributes.ReadOnly) file.Attributes &= ~FileAttributes.ReadOnly; file.Delete(); } } } foreach(var dt in allDocTypes) { var xdoc = XDocument.Parse(dt.ToXml(xmlDoc).ToString()); var file = storageFolder + dt.Alias + ".config"; var fileOnFileSystem = new FileInfo(HttpContext.Current.Server.MapPath(file)); if (fileOnFileSystem.Exists) { if (fileOnFileSystem.Attributes == FileAttributes.ReadOnly) fileOnFileSystem.Attributes &= ~FileAttributes.ReadOnly; fileOnFileSystem.Delete(); } xdoc.Save(fileOnFileSystem.FullName); } } } } }
I'll look at cleaning this up and testing it soon and releasing it as an actual Umbraco package, but in the mean time feel free to have a play around with it.