I'm trying to see if I can over-ride the datasource location of an image field for content editors when selecting the data source (not at render time). E.g in the browse media dialog window that is displayed. This needs to work for both Content Editor and Experience Editor.
It doesn't look to be possible and involves instead creating a custom copy of the image field instead:
How to change the source from an image field programmatically? https://stackoverflow.com/questions/24540419/sitecore-programmatically-change-imagefield-datasource Sitecore Image Field Source to filter on template type
It seems like quite a bit of work just to do this. I wondered if there is a pipeline I can hook into instead to achieve this?
I'm using Sitecore 8.2 update 7.
Update
Attempt 1 - I tried using setting the field datasource to: code:MyCustom.CodeSource, MyCustomAssembly
with code similar to Pete's answer here: Override the source of a template field.
internal class CustomCodeSource
{
[UsedImplicitly]
public void Process(GetLookupSourceValueListsArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (!args.Source.StartsWith("code:")) return;
var values = RunEnumeration(args.Source);
if (values != null && values.Length > 0)
args.Result.AddRange(values);
args.AbortPipeline();
}
private static string[] RunEnumeration(string templateSource)
{
templateSource = templateSource.Replace("code:", string.Empty);
var valueList = ReflectionUtility.CreateInstance(Type.GetType(templateSource)) as IValueList;
return valueList == null ? new string[0] : valueList.ValueListQuery();
}
}
This doesn't fire for Image fields for some reason but does for other types such as Multilist fields.
Attempt 2 - As it was mentioned in the Comments that SXA support this too (https://doc.sitecore.com/developers/sxa/19/sitecore-experience-accelerator/en/use-a-prefix-to-set-the-data-source-context.html) I've tried adding similar code to the SXA CodeDatasource for both the getLookupSourceItems and resolveRenderingDatasource pipeline as I wondered if SXA's pipelines had something magic in them (that maybe supports image fields) given that it overrides the CustomDataSource from the Sitecore.Buckets dll like so:
<getLookupSourceItems>
<processor patch:instead="*[@type='Sitecore.Buckets.FieldTypes.CustomDataSource, Sitecore.Buckets']"
type="Sitecore.XA.Foundation.LocalDatasources.Pipelines.GetLookupSourceItems.CodeDatasource, Sitecore.XA.Foundation.LocalDatasources" resolve="true" />
</getLookupSourceItems>
Here is my code:
public class GetCustomLookupSourceItems
{
public CodeDatasourceService CodeDatasourceService { get; set; }
public GetCustomLookupSourceItems()
{
this.CodeDatasourceService = new CodeDatasourceService();
}
public void Process(GetLookupSourceItemsArgs args)
{
Assert.IsNotNull((object)args, nameof(args));
if (!args.Source.StartsWith("code:", StringComparison.OrdinalIgnoreCase))
return;
foreach (string oldValue in ((IEnumerable<string>)args.Source.Split('|')).Where<string>(
(Func<string, bool>)(x => x.StartsWith("code:", StringComparison.OrdinalIgnoreCase))))
{
args.Source = args.Source.Replace(oldValue, string.Empty).TrimStart('|').TrimEnd('|');
string typeName = oldValue.Replace("code:", string.Empty);
if (args.Item != null)
{
Item[] datasoureces = CodeDatasourceService.GetDataSources(args.Item, typeName);
if (((IEnumerable<Item>)datasoureces).Any<Item>())
args.Result.AddRange(datasoureces);
}
}
if (args.Source.Length != 0)
return;
((PipelineArgs)args).AbortPipeline();
}
}
It's patched in like so:
<getLookupSourceItems>
<processor
patch:instead="*[@type='Sitecore.Buckets.FieldTypes.CustomDataSource, Sitecore.Buckets']"
type="MyCustom.GetCustomLookupSourceItems, MyCustomAssembly">
</processor>
</getLookupSourceItems>
(CodeDatasourceService is pretty much like the SXA one but is concrete for now)
I also added similar code to the SXA ResolveRenderingDatasource.CodeDatasource and patched it in like so:
<resolveRenderingDatasource>
<processor type="MyCustom.ResolveCustomRenderingDatasource, MyCustomAssembly" resolve="true" />
</resolveRenderingDatasource>
Lastly I then tried setting the image field datasource to: code:MyCustom.CodeSource, MyCustomAssembly
hoping the SXA approach would mean it would now work for image fields. Again this doesn't work, it is never called for image fields for some reason.
Has anyone done this successfully in another way?
I'm stumped and it feels like I'm going to have to go with replacing the field which seems pretty horrible and I'd really rather not do this: https://sitecoreoverload.blogspot.com/2018/09/adding-dynamic-image-source-for-multi.html.