Publishing a component which has multiple dynamic templates will usually result in all the possible dynamic component presentations being published to the broker.
When you create a DCT with the option to place the item on a page, a content editor may not want to publish the components directly, simply relying on the Page publish to do the right thing. We could consider three possible desired publishing scenarios:
Tridion's default behaviour appears to be scenario 2), whereas my experience is that often what you want is scenario 3), giving you a complete and consistent view of any given component on the CD side.
What is the best way to implement scenario 3 (including getting unpublish to work correctly)?
In my opinion, the best answer for your question is to implement a custom Resolver that would include the required Dynamic Component Presentations. I would be wary of doing anything when unpublishing, as sometimes you may want to keep the DCPs after unpublishing a given page (for "latest news" type of functionality or any other sort of dynamic queries), but the code sample below would make it simple for you to adapt if you need to unpublish all DCPs.
Warning: Below code is not production-tested.
using Tridion.ContentManager;
using Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.Publishing;
using Tridion.ContentManager.Publishing.Resolving;
public class IncludeDynamicComponentPresentations : IResolver
{
public void Resolve(
IdentifiableObject item,
ResolveInstruction instruction,
PublishContext context,
Tridion.Collections.ISet<ResolvedItem> resolvedItems)
{
if (!(instruction.Purpose == ResolvePurpose.Publish ||
instruction.Purpose == ResolvePurpose.RePublish))
{
// Do nothing more when unpublishing
return;
}
Session session = item.Session;
foreach (ResolvedItem resolvedItem in resolvedItems)
{
// Only do something if we're dealing with a page
if (!(resolvedItem.Item is Page)) continue;
Page page = (Page)resolvedItem.Item;
if (page.ComponentPresentations.Count > 0)
{
UsingItemsFilter filter = new UsingItemsFilter(session);
filter.InRepository = page.ContextRepository;
filter.ItemTypes = new[] { ItemType.ComponentTemplate };
foreach (ComponentPresentation cp in page.ComponentPresentations)
{
// Find all component templates linked to this component's schema
Schema schema = cp.Component.Schema;
foreach (ComponentTemplate ct in schema.GetUsingItems(filter))
{
if (!ct.Id.Equals(cp.ComponentTemplate.Id))
{
if (ct.IsRepositoryPublishable)
{
resolvedItems.Add(new ResolvedItem(cp.Component, ct));
}
}
}
}
}
}
}
}
You would now need to add this to the GAC and modify [Tridion]\Config\Tridion.ContentManager.Config so this Resolver is called after every resolve action (under resolving/mappings for every item type).
Perhaps a Custom Resolver would help in this situation? This would give you access to all the items the result from a publish action, allowing you to change the default behaviour.
There's a good example of this in the SDL Tridion documentation portal, but it basically allows you to create a custom resolver class in .net, where you can implement your custom logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With