Friday, July 9, 2010

Moss2007: Adding button to Publishing Edit Console via Feature

To add a button to the Publishing Edit Console it's advised to modify the CustomQuickMenu.xml file of your SiteCollection. Most information describe the procedure to overwrite the default file. When multiple solutions would use this method of overwriting, they would discard each others modifications. It would be much better to parse the xml file and only add/delete it's own modifications. The code of the FeatureReceiver posted here does just this. It uploads it's own .xml file and adds a reference for this xml file to the CustomQuickMenu.xml. Upon deactivation of the Feature, all modifications will be restored.

class DependencyQuickAccessButtonFeatureReceiver : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPSite site = (SPSite)properties.Feature.Parent;
SPFolder editingmenufolder = site.RootWeb.GetFolder("/_catalogs/masterpage/Editing Menu/");
Stream dqabstream = this.GetType().Assembly.GetManifestResourceStream("Macaw.Wss3.DependencySpiderSolution.FeatureCode.DependenciesQuickAccessButton.xml");
SPFile dqabfile = editingmenufolder.Files.Add("DependenciesQuickAccessButton.xml",dqabstream,true);
dqabfile.CheckIn("Added by DependencySpiderSolution");
try
{
dqabfile.Publish("Added by DependencySpiderSolution");
}
catch { }

SPFile file = site.RootWeb.GetFile("/_catalogs/masterpage/Editing Menu/CustomQuickAccess.xml");

Stream stream = file.OpenBinaryStream();
XmlDocument document = new XmlDocument();
document.Load(stream);
stream.Close();

XmlNode consolenode = document["Console"];
if (consolenode == null)
{
consolenode = document.AppendChild(document.CreateElement("Console"));
}

XmlNode customfilenode = consolenode.SelectSingleNode("/Console/customfile[@FileName='DependenciesQuickAccessButton']");
if (customfilenode == null)
{
customfilenode = consolenode.AppendChild(document.CreateElement("customfile"));

XmlAttribute filenameattribute = customfilenode.Attributes.Append(document.CreateAttribute("FileName"));
filenameattribute.Value = "DependenciesQuickAccessButton";
}

stream = new System.IO.MemoryStream();
StreamWriter writer = new StreamWriter(stream, Encoding.ASCII);
document.Save(writer);
writer.Flush();

file.CheckOut();

file.SaveBinary(stream);

file.CheckIn("Added DependencyQuickAccessButton");
try
{
file.Approve("Added DependencyQuickAccessButton");
}
catch { }
}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPSite site = (SPSite)properties.Feature.Parent;

#region Restore "CustomQuickAccess.xml"
SPFile file = site.RootWeb.GetFile("/_catalogs/masterpage/Editing Menu/CustomQuickAccess.xml");

Stream stream = file.OpenBinaryStream();
XmlDocument document = new XmlDocument();
document.Load(stream);
stream.Close();


XmlNode customfilenode = document.SelectSingleNode("/Console/customfile[@FileName='DependenciesQuickAccessButton']");
if (customfilenode != null)
{
customfilenode.ParentNode.RemoveChild(customfilenode);
}

stream = new System.IO.MemoryStream();
StreamWriter writer = new StreamWriter(stream, Encoding.ASCII);
document.Save(writer);

file.CheckOut();
file.SaveBinary(stream);

file.CheckIn("Removed DependencyQuickAccessButton");
try
{
file.Approve("Removed DependencyQuickAccessButton");
}
catch { }
#endregion

#region Delete "DependenciesQuickAccessButton.xml"
SPFile dqabfile = site.RootWeb.GetFile("/_catalogs/masterpage/Editing Menu/DependenciesQuickAccessButton.xml");
if (dqabfile != null && dqabfile.Exists)
{
dqabfile.Delete();
}
#endregion

}

public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{

}

public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{

}
}

I used these sites as information source:
http://community.zevenseas.com/Blogs/Robin/archive/2010/06/07/sharepoint-file-encoding-and-uploading-the-customquickaccess-xml.aspx