March 25, 2010 by Alistair Deneys
Revolver is a very flexible tool for helping developers and administrators do stuff in Sitecore. Recently I was part of or witness to some queries about how to do some things in Sitecore that weren’t apparent, or simply cannot be done without your own customisation. These queries touched on 2 of the tenants of Revolver; these are to fill in the gaps of the current UI (in terms of functionality), and to provide fast access to the content tree.
I’ve described the queries below and how to achieve each using Revolver.
Copy content between languages
First for the query with the shorter answer. The query was about some facility to copy content between languages. I think the actual scenario was creating a new translation in a similar language (such as Australian English and American English) but the user wanted to use the content from the other language as the basis for the new translation.
Revolver allows you to do this very easily. In fact, Revolver contains a command for copying content between languages; the
cpl will copy all fields of the current language to a target language. By default this command will not copy over fields which are already populated in the target language, just in case someone did start translating fields. To change that and have all fields overwritten just pass the overwrite (-o) parameter to the command.
cpl -o da
If I only wanted to copy a single field I can do that as well, though it’s a little more involved. The basic process involves storing the current language value of the field in an environment variable, changing to the target language and setting the field of the item from the environment variable.
set f < (gf -f text) cl da sf text ($f$)
The first line above stores the current value of the text field into an environment variable called “f”. We use sub commands (the < symbol) to use the output of a command as the parameter to another. The second line changes the language to Danish. The third line sets the text field from the environment variable. To use the value of an environment variable we just enclose the variable name in dollar signs.
We can make this process a little more usable by putting the above commands into a script. Revolver supports grouping multiple commands into scripts which are stored in the core database. Scripts also allow passing parameters into them. So if we took the above and put it into a script which accepted as the first parameter the field, the second parameter the source language and the third parameter the target language, we might have a script that looks like below.
cl $2$ set f < (gf -f $1$) cl $3$ sf text ($f$) set f cl $2$
To use the parameters passed into the script we use the same notation as for environment variables except we reference the 1-based index of the parameter being passed.
The first line above changes to the source language. Lines 2, 3 and 4 are the same as the original commands except we’re using parameters instead of the hard coded values for target language and field. Line 5 clears the environment variable (which is good practise when using environment variables in a script) and the 6th line changes back to the source language.
If we named the above script
cpf, then the following invocation would copy the text field from English to Danish.
cpf text en da
Report of changed items
The next query was from a user wanting to creating a Sitecore package of changes between their development (or QA) environment content and their production content. Initially I answered this question with a wrong answer; I said I didn’t know of any functionality in Sitecore that would allow you to do this. This is wrong.
Since Sitecore 6 the Sitecore packager has contained a feature called “dynamic sources”. Dynamic sources allow you to include items and files into a package using a filtering approach rather than specifying each item individually. Kerry Bellerose has blogged previously about the benefits of using dynamic sources in packages.
With a dynamic item source I can specify a root node to start inclusions from (such as the
/sitecore/content item) and then apply a variety of filters to the descendants of the root location including filtering on name (including using regular expressions), creation or modification date (including absolute dates as well as number of days old), publication date, filtering on template, filtering on the user who created or updated the item and language. So using a dynamic item source it’s very easy to create a package of all changes since a certain date. As long as you know the date of the previous release then this approach will work.
The reason I initially provided a wrong answer to this query was because I didn’t read it correctly. This may be because I was imposing my own release practises onto the question.
During development (or QA) you will end up with a lot of test content being created to properly test each facet of whatever feature you’re releasing. Generally you don’t want this content to be included in the release package, but sometimes you might, especially if the content in question is not test content but is in fact a new site section of configuration / setting you do want included in the release package.
For this reason, when I create a release package I want to specify each item which gets included. To do this in the most efficient manner I need a report of all of the items which have changed since the last release was made. This is how I read that initial question: “How can I generate a report in Sitecore of all items which have changed since a certain date”. And of course, Revolver does this really well.
Whilst on the subject of dynamic item sources, I’ve also heard a lot of people say they don’t trust dynamic item sources. And I can’t say why, as I don’t generally hold this opinion. The package designer even allows you to search for items included in a source, so I don’t know why people don’t trust it. Perhaps it’s because of what I describe above about them wanting to exclude the test content.
There are 2 commands in Revolver which allow querying of the content tree and can be used for the task of generating a list of changed items. These are the
find command and the
find command allows you to execute a command against a number of items which match a filter. By default the current context item is used as the root for the search but this can be changed by passing a path into the
path parameter of the command. By default find will only execute for the child of the current item. To search the descendants you need to pass the recursive (-r) parameter as well.
The filtering on the find command allows the following options:
- Filter on template
- Filter on branch
- Filter on field value
- Filter on expression
- Filter on attribute (id, name, key, template, templateid, branch, branchid)
Most of the above should make sense to you, except the expression filter. Expressions are a Revolver feature to allow filtering based on boolean logic and comparison of constants and field values. And it’s this filter that will be used when generating a list of changed items over a given date range. For more information on expressions simply type
help expressions in the Revolver command window.
Sitecore stores the date an item was created and updated in the
__updated fields respectively. The field filter of the find command will allow matching the string value of a field against a given constant, but won’t allow tests such as greater than and less than which we would need for a date range filter. The expression filter does allow this.
So to generate a list of recently created items in the current location I can simply execute the following command.
find -e (@__created > 1/1/2010 as date) pwd
That will generate a list of all items created after 1st January 2010. Breaking the expression down, first we provide a field name of __created as the first argument of the expression. The single
@ denotes a field name. Next is the operator which in the above case is “greater than”. The constant we’re comparing the field value against is given as 1/1/2010. If the comparison was done as a normal string then we’re get unexpected results as Sitecore stores datetimes in an ISO format of
yyyyMMddThhmmss. So we need to tell the expression engine to perform the evaluation as a date which is what the “as date” on the end does. The
pwd on the end is the command we have
find execute against each matched item.
pwd just displays the current item’s path.
If we wanted to search all descendants as well we would have to add the recursive parameter (-r) to the find command.
find -r -e (@__created > 1/1/2010 as date) pwd
The other command Revolver offers for searching content is the
query command which simply allows executing Sitecore query against the content tree. This command also supports fast query.
query (*[@@__created > 20100101]) pwd
Or if we wanted to search all items recursively:
query (.//*[@@__created > 20100101]) pwd
The thing to note about using Sitecore query is that if you get a large number of results you might not have them all. This is because of the
Query.MaxItems setting in
web.config which limits the maximum number of items which can be returned in a Sitecore query. The find command however does not use Sitecore query and just uses the API, so you can be guaranteed when using find that all matching items have been returned.