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.