Rules rule

My content editors usually use the Content Editor to edit their items. For some reason, if there’s errors (i.e. required fields or items on the same level with the same name) they don’t always notice. I decided to make it a bit more noticeable, by creating one of those yellow bars on top of the item if there’s errors leading to not being able to go through workflow.

I figured there’d be something like Sitecore.Context.Item.Validation.IsValid or similar, but that wasn’t the case. There also wasn’t an existing Rule I could find that would give me whether the item was valid. Time to do some customization then!

Using Sitecore Rocks I created a class based on a Rule (Sidenote: Don’t have Sitecore Rocks yet? Get it here, now! It makes things a lot easier).

Insert through Rocks

Supposedly Sitecore would automatically make the Sitecore Item as well, but that didn’t happen in my case. That’s fine, I just created a Rule Item linking it up to my code.

rule item

As you can see, I could make an easy rule as I don’t need any variables apart from the item. I just want it to tell me when it’s either a critical error, fatal error or error.

The actual condition code I created was very easy, as I decided to make an extension method for the Item. This is the code for the condition:

publicclassItemValidCondition<T> : WhenCondition<T> where T : RuleContext
{
    protectedoverridebool Execute(T ruleContext)
    {
// Return true, if the condition is satisfied.
        return ruleContext.Item.IsValid();
    }
}

Then all I need to do is create the extension method. This was more tricky than I would’ve liked at first (although it ended up being fairly simple). I came across this blogpost by Aaron Blake:

That all seemed a bit too much to just validate an item. I ended up with something very similar – I just removed a lot of code, so I’d end up with the following:

var formValue = WebUtil.GetFormValue(“scValidatorsKey”);

if (!string.IsNullOrEmpty(formValue))
{
    var validators = ValidatorManager.GetValidators(ValidatorsMode.ValidatorBar, formValue);
    var options = newValidatorOptions(true);
    ValidatorManager.Validate(validators, options);

    foreach (BaseValidator baseValidator in validators)
    {
        if (baseValidator.Result == ValidatorResult.CriticalError ||
            baseValidator.Result == ValidatorResult.FatalError ||
baseValidator.Result == 
ValidatorResult.Error)
        {

            return false;
        }
    }
}

Initially, this seemed to work, but I ended up having 2 issues.

1 – Doesn’t show the errors in Sitecore Rocks – Rocks doesn’t have the scValidatorsKey since it’s not using a form to get the key out of.
2 – When browsing around I noticed it had a ‘delay’ of 1 item. When I selected an item I knew had an error it showed me that it was fine, when I then browsed to a different item (which I knew to be correct) it displayed my warning. I don’t know whether Aaron’s code also has this issue as I haven’t tested that, I just started modifying it.

What I thought was interesting was the ValidatorManager. I figured I could get the validators from the item that way then, instead of using the key.

That meant the GetValidators() method was out, since that requires a key. Other options are:
– GetGlobalValidatorsForItem
– GetItemValidators
– GetFieldsValidators

The GlobalValidatorsForItem returned some for me, but not the ones I expected. GetItemValidators returned none, which I kind of expected as I didn’t have any validators on the item – just on the fields.

I couldn’t figure out the second parameter in GetFieldsValidators though.

GetFieldsValidators

It doesn’t take in the actual fields, but an enumeration of FieldDescriptor. I didn’t want to create a FieldDescriptor for each field, so I decided to look further. If you have any information on this FieldDescriptor or how the GetFieldsValidator works, please leave it in a comment below.

I started some Googling again, and came across this StackOverflow question in which Stephen Pope mentions the ValidatorManager.BuildValidator method. That kind of does what I want, but I want to validate all rules, not just the one (or ones) I select. I want to keep in mind that if a validator gets added, I still want my validator to work. Turns out, there’s also a ValidatorManager.BuildValidators() method.

My final code for the extension method:

public static class ItemExtensions
{
    ///<summary>
    /// Check if the validators of the Workflow validators are valid
    ///</summary>
    ///<param name=”item”>The item</param>
    ///<returns>True if all validators return ValidatorResult.Valid. False otherwise</returns>
    public static bool IsValid(thisItem item)
    {
        var validators = ValidatorManager.BuildValidators(ValidatorsMode.Workflow, item);
        var validatorOptions = newValidatorOptions(true);
        ValidatorManager.Validate(validators, validatorOptions);

        foreach (BaseValidator baseValidator in validators)
        {
            if (baseValidator.Result == ValidatorResult.CriticalError ||
baseValidator.Result ==
ValidatorResult.FatalError ||
baseValidator.Result == 
ValidatorResult.Error)
            {
                return false;
            }
        }

        return true;
    }
}

Notice I’m using the ValidatorMode.Workflow, which is how I only validate the items in the worflow validation that’s been applied.

So now I could create my custom rule:

 rule

rule text

Which uses the existing action to show the warning.

And this is what it looks like in Sitecore Rocks:

result

Advertisements

Changing icons for insert options

Since my StackOverflow answer for that question seemed to be very popular, I figured I’d dedicate a blog post to the topic. 
The question basically boils down to “How can I change the icons for the insert options?”.

Image

Instead of the default images for the sublayout  and renderings when inserting a new component we’d like to see something more descriptive. This way it makes it a bit easier on content editors when they’re looking for a control in a long list – even if the name doesn’t make a lot of sense to them.

So what we can do is go to the sublayout or rendering, find the Appearance  section and select the Thumbnail image.

Image

‘Take screenshot’ opens a new window in which we can tell Sitecore to either use an item to browse to by selecting the item and the device or put in a URL. Sitecore then shoots off a request to the selected item, and renders it in the new window.

Image

Then, after selecting the proper area of the website, click OK. This is now selected as the image (which you can preview on the right-hand side).

Of course, if you already have images in your media library which you’d like to use, you can just select it using the Browse button. If the size isn’t correct, it’ll shrink/ stretch the image.

When we now try and insert a new component we get the following:

Image

Way better, I think.

Those screenshots will be saved in the Media Library, under the System node, then folders for the first 4 characters of it’s GUID:

Image