Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When DCPs are placed on a page in Tridion, how can you ensure that all the dynamic renderings of the component are published with the page?

Tags:

tridion

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:

  1. That publishing the page should only cause the static component presentations to be rendered, (plus whatever CD code is necessary to display the dynamic ones)
  2. That in addition to static CPs, any dynamic CPs should be published. Other possible dynamic renderings of the same component are not published.
  3. If a dynamic CP is published, the usual component publishing semantics are followed, and all dynamic renderings will go to the broker.

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)?

like image 633
Dominic Cronin Avatar asked Feb 18 '12 13:02

Dominic Cronin


2 Answers

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).

like image 192
Nuno Linhares Avatar answered Nov 09 '22 16:11

Nuno Linhares


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.

like image 26
Dave Houlker Avatar answered Nov 09 '22 16:11

Dave Houlker