Monday, March 15, 2010
Sitecore Friendly URLs and plus sign
There are at least two ways to accomplish this:
1. Allow “+” in item name via a configuration change
For this you will need to adjust the regular expression in the “ItemNameValidation” setting in web.config and make sure + sign is not present in the “InvalidItemNameChars” setting.
2. Rely on the display name instead.
Thursday, March 11, 2010
Publish to pre-production web database
In my experience with enterprise level implementations, there is often a need for a separate “stage environment” for final content preview or a pre-production phase of workflow.
It is also often the case that the environmental limitations or restrictions make the content delivery part of the authoring environment suitable for such purpose. For example, your e-commerce infrastructure could not be available from the authoring instance. One of the possible ways to approach such a requirement is to configure a stand-alone staging instance of Sitecore which will be used for content delivery instance and is commonly configured exactly like one of the servers in the web farm. There is one exception though – the database that is used for content delivery is generally different from the one that is used in production content delivery.
With this approach, now the question is how to plug in workflow in a way that content could go via this “stage” environment and then only upon final approval will be able to get to “production”.
Now there is a problem that you cannot get get items published until they are in final workflow state. You could have two workflow states “Staged” and “Published”, both marked as final and with auto publish actions connected.
I don’t like this approach since it goes against the workflow nature – only one state should be marked as final.
Alternatively, you can plug in a “copy item” workflow action to the “Staged” workflow state where you can programmatically copy an item from master database to stage web.
While this approach does seem legitimate, it works around the need of publishing thus any additional processing you may be having in publish(item) pipeline would not work.
I looked into the option of having publishing process ignore workflow when publishing to stage. While this seemed like a dangerous path to go, I have soon discovered that the PublishHelper’s GetVersionToPublish method already accepts this notion of passing a “requireapproval” flag to the underlying publishing mechanism. Since it is always passes “true”, I started looking into ways to make this flag dynamic and figured that setting it on the level of PublishOptions could be a good idea. For example, from the code of my workflow action I would be able to define whether I want to have workflow respected or not.
Here is what you will need to do to make it work.
First, override the default PipelinePublishProvider and plug it into the web.config:
<publishManager defaultProvider="default" enabled="true"> <providers> <clear /> <!--<add name="default" type="Sitecore.Publishing.PipelinePublishProvider, Sitecore.Kernel" />--> <add name="default" type="SCUSAINC.Publishing.ExtendedPublishProvider, SCUSAINC.Publishing" /> </providers> </publishManager>
Secondly, you will need to override the CreatePublishHelper class:
public class ExtendedPublishProvider : PipelinePublishProvider { public override PublishHelper CreatePublishHelper(PublishOptions options) { Assert.ArgumentNotNull(options, "options"); if (options is ExtendedPublishOptions) return new ExtendedPublishHelper(options as ExtendedPublishOptions); return new PublishHelper(options); } }
After that, introduce two more classes – ExtendedPublishHelper and ExtendedPublishOptions:
public class ExtendedPublishHelper : PublishHelper { private readonly ExtendedPublishOptions _options; public ExtendedPublishHelper(ExtendedPublishOptions options) : base(options) { _options = options; } public override Item GetVersionToPublish(Item sourceItem) { Assert.ArgumentNotNull(sourceItem, "sourceItem"); if (Options is ExtendedPublishOptions) { return sourceItem.Publishing.GetValidVersion(Options.PublishDate, _options.RequireApproval); } return sourceItem.Publishing.GetValidVersion(Options.PublishDate, true); } } public class ExtendedPublishOptions : PublishOptions { public ExtendedPublishOptions(Database sourceDatabase, Database targetDatabase, PublishMode mode, Language language, DateTime publishDate, bool requireApproval) : base(sourceDatabase, targetDatabase, mode, language, publishDate) { RequireApproval = requireApproval; } public bool RequireApproval { get; set; } }
Now you are ready to launch publishing with workflow settings completely ignored. For example, this is how you can do it from the workflow action:
var database = Factory.GetDatabase(databaseName); var options = new ExtendedPublishOptions(dataItem.Database, database, PublishMode.SingleItem, dataItem.Language, DateTime.Now, false) { RootItem = dataItem, Deep = true; }; new Publisher(options).PublishAsync();
3/11/2010: Correction » the last parameter of the ExtendedPublishOptions constructor should be “false”.
Instead of hardcoding it, I’d suggest having a parameter on the level of a workflow action which you can read and pass on.
private static bool RequireApproval(string parameters) { return WebUtil.ParseUrlParameters(parameters)["RequireApproval"] == "true"; }
public void Process(WorkflowPipelineArgs args) { ... var requireApproval = RequireApproval(innerItem["parameters"]); var options = new ExtendedPublishOptions(dataItem.Database, database, PublishMode.SingleItem, dataItem.Language, DateTime.Now, requireApproval) ... }
That’s it!
Tested on Sitecore 6.1. Expected to work with 6.2.
Sitecore startup time - something that could improve it
So I decided to spend some time on the problem and engaged our brilliant technical support into this little project.
Wednesday, March 10, 2010
Things to consider when using Sitecore Packager
It is going to be a quick one. There is a simple checklist of things that you can use to help Packager be your friend.
1. Don’t include stuff you don’t need to. I see people including the whole folder with system templates instead of adding only custom templates or just changed fields on the system templates if there are any.
2. Use PChex component to verify package integrity.
3. Prefer dynamic sources over static sources. Kerry describes why here.
4. Disable search index to improve performance of package installation.
5. Get yourself familiar with the Installation Options. Use “Overwrite” very, very carefully as it may overwrite the branches.
6. Predefine those installation options. If somebody else is going to install your package, you don’t want them to choose for you.
7. Though readme gets ignored in most cases, do your best to supply the installation information or post-install directions with the package metadata.
8. Make sure to save the package project (xml file).
I realize that this may not be a complete list, so please feel free to share your experience and do comment.
Thanks!
Tuesday, March 09, 2010
Read only view of Rich Text field for Sitecore editor
Today I want to share an idea of a lightweight customization for Sitecore CMS that meant to increase usability of the rich text field for your editors. The idea is inspired by great feedback I received recently while being in the field.
The basic problem reported by one of the editors who uses Sitecore on the daily basis, is that when a content item is approved in workflow there is no way to see what’s inside of a rich text field easily. All field buttons are grayed out thus disabled:
…so the only way is to click “Lock and Edit” which creates a new version:
As you can imagine, this is not generally acceptable. If your non-admin editor user simply wants to see what’s in there, you don’t want a new version to be created.
Now it is worth mentioning that the item which is approved, unlocked is disabled for editing only if “RequireLockBeforeEditing” setting is set to true which is often the case, since you would want to have “Lock and Edit” in place so new version of the approved content is created.
Same goes along with the items that are locked. If there is a locked item, I would still want to see the content of the rich text field in read-only mode.
So one of the easiest ways I could think of to address this was enable “preview” of the rich text field in a modal dialog on double click.
Tech support provided the following solution which enabled the double click on disabled rich text field and showed the “preview” version of the field in a modal dialog:
To make it work, follow these steps:
1. Open Preview.aspx under /sitecore/shell/Controls/Rich Text Editor.
2. Locate the scEdit() function and comment out the first IF statement:
function scEdit() { //if (scDisabled == "1") { // return; // } var form = scGetForm(); ...
3. Compile the following code:
namespace Company.Web.Fields { using Sitecore.Diagnostics; using Sitecore.Shell.Applications.ContentEditor.RichTextEditor; using Sitecore.Web.UI.Sheer; public class RichText : Sitecore.Shell.Applications.ContentEditor.RichText { protected new void EditText(ClientPipelineArgs args) { Assert.ArgumentNotNull(args, "args"); if (Disabled && !args.IsPostBack) { var url = new RichTextEditorUrl { Conversion = RichTextEditorUrl.HtmlConversion.Runtime, Disabled = Disabled, FieldID = FieldID, ID = ID, ItemID = ItemID, Language = ItemLanguage, Mode = string.Empty, Source = Source, Url = "/sitecore/shell/Controls/Rich Text Editor/Preview.aspx", Value = Value, Version = ItemVersion }; var str = url.GetUrl(); SheerResponse.ShowModalDialog(str.ToString(), "800px", "500px", string.Empty, true); args.WaitForPostBack(); } base.EditText(args); } } }
4. In web.config, add your own controlSource reference to the namespace above:
<controlSources> <source mode="on" namespace="Sitecore.Web.UI.XmlControls" folder="/sitecore/shell/override" deep="true" /> ... <source mode="on" namespace="Company.Web.Fields" assembly=" Company.Web" prefix="custom" /> </controlSources>
5. In the core database, locate the Rich Text field item (/sitecore/system/Field types/Simple Types/Rich Text) and adjust the value of the “control” field:
custom:RichText
Note that the prefix is used from the controlSource reference above.
Simple and lightweight customization that should bring some value. Sitecore rocks!
Tested on 6.1, expected to work on 6.0.x and 6.2.