Nibble

Archive for July, 2010

Updating the locator package to support umbraco 4.5 0

As you may know there are some changes in umbraco 4.5 that might require some packages to be updated in order to be compatible with umbraco 4.5. This post outlines what I did to update the locator package with 4.5 support.

What’s important for me is that I don’t want multiple versions of the code/package depending on the umbraco version but would like to handle that in the code/installer instead. So that I have a single package that can be used on both 4.0.X and 4.5.

Identifing what schema the site is running on

In the locator package there is an xslt file to transform the results and also in the code there are several actions that manipulate the content xml, so before I can do any updates I need to know what schema the current site is using.

In umbraco 4.5 there is a new setting UmbracoSettings.UseLegacyXmlSchema (which is pulled from the /config/umbracoSettings.config), this isn’t there in umbraco version older then 4.5, so if you try to get that value and it fails because of a MissingMethodException then it should be an older version then 4.5 (and thus on the old schema)

bool useLegacySchema = true;
try { useLegacySchema = Utility.UseLegacySchema; }
catch (MissingMethodException) { }


Updating the code

In the locator package I manipulate the content xml and add some nodes (extra properties on documents) on the fly so depending on the schema I need to add

<data alias=”myAlias”>value</data> (old schema) or simply <myAlias>value<myAlias> (new schema).

After the update the code that does that looks like this:

bool useLegacySchema = true;
try { useLegacySchema = Utility.UseLegacySchema; }
catch (MissingMethodException) { }
XmlElement distanceNode =
content.CreateElement(useLegacySchema ? "data" : "distance");
distanceNode.InnerText = distance.ToString(Utility.NumberFormatInfo);
if (useLegacySchema)
{
XmlAttribute aliasAttribute = content.CreateAttribute("alias");
aliasAttribute.Value = "distance";
distanceNode.Attributes.Append(aliasAttribute);
}
node.AppendChild(distanceNode);


Updating the package, installing the correct xslt file

The locator package installs an xslt file (LocatorResults.xslt) that is used to transform the search results. Depending on what schema the current site is using it needs to install the correct version, this is handled by a custom package action.

In the package I simply include an additional xslt file LocatorResultsNewSchema.xslt (the new schema version)

But I let the installer place this in the /data/packages/temp directory

So in the package.xml I have this part:

<file>
<guid>LocatorResults.xslt</guid>
<orgPath>/xslt</orgPath>
<orgName>LocatorResults.xslt</orgName>
</file>
<file>
<guid>LocatorResultsNewSchema.xslt</guid>
<orgPath>/data/packages/temp</orgPath>
<orgName>LocatorResultsNewSchema.xslt</orgName>
</file>

Which will copy the LocatorResults.xslt file(using the old schema) in the package to the /xslt directory and the LocatorResultsNewSchema.xslt(using the new schema) to the /data/packages/temp directory.

At this point the xslt using the old schema is installed in the /xslt directory, so now if the site is using the new schema I simply need to move the LocatorResultsNewSchema.xslt file to /xslt/LocatorResults.xslt.

That’s done with a custom package action

The package action Xml looks like this:

<Action runat="install" alias="addNewSchemaContentToFile">
<source>/data/packages/temp/LocatorResultsNewSchema.xslt</source>
<target>/xslt/LocatorResults.xslt</target>
</Action>

The source node contains the path to the new schema xslt file and the target node contains the path to the location of the xslt file to overwrite.

The package action then simply checks if the current site is using the new schema, if it is it deletes the existing xslt file (the one using the old schema) and then moves the xslt file that’s using the new schema to that location. If the site is on the old schema it will simply delete the new schema xslt file.

public bool Execute(string packageName, System.Xml.XmlNode xmlData)
{
string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
string sourceFile = xmlHelper.GetNodeValue(xmlData.SelectSingleNode("source"));
string targetFile = xmlHelper.GetNodeValue(xmlData.SelectSingleNode("target"));
try
{
if (!Utility.UseLegacySchema)
{
if (File.Exists(basePath + sourceFile))
{
if (File.Exists(basePath + targetFile))
File.Delete(basePath + targetFile);
File.Move(basePath + sourceFile, basePath + targetFile);
}
return true;
}
else
{
File.Delete(basePath + sourceFile);
return true;
}
}
catch(MissingMemberException)
{
File.Delete(basePath + sourceFile);
return true;
}
}

 

That’s what it took to update the locator package (in this case it was all related to the schema changes), the new package is available on the locator project page at our.umbraco.org and sourcecode is available on codeplex.