Has anyone got any ideas on how to customise the “choose data source dialog” / pipelines; so that only certain items (by tag or otherwise) are available as the selectable data source?
2 Answers
Prepare for a huge wall of text here which is not tested, but should work in theory and is a perfect blog post material :)
So the easiest way to do this, is to actually act to the unselectable items in the same way that Sitecore reacts to the unselectable templates - i.e. showing a message and telling that this is not a valid choice.
So the first stop should be GetRenderingDataSource Pipeline
and GetRenderingDataSourceArgs
.
You need to create a Custom GetRenderingDataSourceArgs
(inheriting from the existing ones) that will host your custom rules.
After this being applied you need to create a custom processor and plug it in right before <processor type="Sitecore.Pipelines.GetRenderingDatasource.GetDialogUrl, Sitecore.Kernel"/>.
Here you are going to plug your processor that is going to apply your custom rules.
Next step would be to override the GetDialogUrl processor
, which is going to spawn the window with the rules applied to it. The problem here is that it uses SelectDatasourceOptions
class which is one more point you will need to extend.
So in the Custom SelectDatasourceOptions
you need to add a place for your custom rules, override the ToUrlString
method and override the Parse
Method, so it can parse correct parameters to the window.
After that you need to go back to the GetDialogUrl Processor
and pass the new parameter.
Now we hopefully will have the window opened and the custom rules paramaters are going to be passed, so the next stop would be the SelectRenderingDatasourceForm
.
Here you will need to have to use your Custom SelectDatasourceOptions
as options. In the parse method (which is actually located in the Property for the Options) I am not 100% sure that you will need to do a new override of the SelectItemOptions.Parse<SelectDatasourceOptions>()
, but it is most likely the case that you will.
In theory now the data which is passed to the dialog should be handled and you are ready to apply the filtering.
The final thing that needs to happen is for you to override the IsSelectable
method in which the actual filtering will happen.
Hope this makes sense !
-
Thanks. Good thorough walkthrough. Should really be a lot simpler than that :-)– EldblomCommented Oct 25, 2016 at 7:50
The pipeline that you need to patch is the getRenderingDatasource
. Below is the different steps that you will require to implement a custom rendering datasouce:
1. Sublayout
In the sublayout, in the Editor Options Section, there is a field called Datasource Location. In this, you can specify the query you want, below is an example of the query:
query:ancestor-or-self::*[@@templatename='Website']//Catalog Container
Note that the query above needs to have a template called Website then get the Catalog Container.
2. Code
Here, it is where you will insert the logic that you will require to have a custom datasource. As example, the below code will execute and will set the window from where content authors select the item to a specific container. Note that this is dynamic. In other words, let's say you have Site A, B and C and all 3 have a catalog container. The below code will render the datasource and content authors will never be able to select catalog from Site A in Site B or C
public void Process(GetRenderingDatasourceArgs args)
{
Assert.IsNotNull(args, "args");
string text = args.RenderingItem["Datasource Location"]; //Get the value from the field
if (!string.IsNullOrEmpty(text))
{
if (text.StartsWith("query:") && !string.IsNullOrEmpty(args.ContextItemPath))
{
var contextItem = args.ContentDatabase.GetItem(args.ContextItemPath);
if (contextItem != null)
{
text = text.Remove(0, 6); //remove the query:
var item = contextItem.Axes.SelectSingleItem(text); //Execute the query
if (item != null)
{
args.DatasourceRoots.Add(item);
}
}
}
}
}
To restrict the content authors from selecting other templates, you can set the Datasource Template
. This allows content authors to select items which are of the same template as specified in the Datasource Template
3. Config
Now you need to patch the getRenderingDatasource
pipeline. Below is how you will need to patch it
<getRenderingDatasource>
<processor type="YourNamespaceHere, YourAssemblyName"
patch:before="processor[@type='Sitecore.Pipelines.GetRenderingDatasource.GetDatasourceLocation, Sitecore.Kernel']"/>
</getRenderingDatasource>