Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tridion RepositoryLocalObject.GetBluePrintChain Method (BluePrintChainFilter) thows exception on shared items

I'm trying to get a list of parent items that a RepositoryLocalObject (e.g. Component) is inherited from. So if I have a pub ID 1 with component tcm:1-80 and a child pub ID 2, then this component is shared in the child pub as tcm:2-80. So I want to get tcm:2-80's parent, or anything that's in the tree moving up.

I've tried the GetBluePrintChain() method on a local copy of a component where it works fine. However, on shared component it returns an InvalidActionException: "This item is shared". The documentation mentions that this exception is thrown on shared items. But how does this make sense? Obviously if any item that has a blueprint chain beyond itself would be shared (or be a local copy). So to me it doesn't make sense to have this method throw an exception on something that has a blueprint chain. It seems contradictory.

My question is somewhat related to Getting root publication of component, but it is different. I need to understand why this exception is thrown on shared items. Can someone please explain and perhaps share a use case to support it?

like image 655
Nickoli Roussakov Avatar asked Oct 30 '12 00:10

Nickoli Roussakov


2 Answers

As far as I know the GetBluePrintChain methods are meant to look down a BluePrint when you're standing at the top of it. So in your case, you should get the item in its owning publication context and then invoke GetBluePrintChain.

Item item = package.GetByName("Component");
Component component = new Component(item.GetAsXmlDocument().DocumentElement,
                                    engine.GetSession());
TcmUri id = TemplateUtilities.CreateTcmUriForPublication(
        component.OwningRepository.Id.ItemId, component.Id);

var blueprintchain = ((Component)engine.GetObject(id)).GetBluePrintChain();

package.PushItem(package.CreateStringItem(ContentType.Text, 
                                          blueprintchain.ToString()));
package.PushItem(package.CreateStringItem(ContentType.Text,
                             ""+System.Linq.Enumerable.Count(blueprintchain)));
foreach (var item in blueprintchain)
{
    package.PushItem(package.CreateTridionItem(ContentType.Component, item));
}

I just ran the above C# fragment as a TBB in two scenarios:

  1. in a child publication on a shared Component
  2. in a child publication on a localized Component

In case 1 the blueprintchain will contain a single item: the shared Component. In case 2 the blueprintchain will contain two items: the shared Component and the localized Component.

like image 124
Frank van Puffelen Avatar answered Nov 13 '22 20:11

Frank van Puffelen


To summarize the answer above, here's a practical work-around for "Item is shared" issue:

Calling GetBluePrintChain() for an arbitrary item that happens to be shared will fail:

return
  item.GetBluePrintChain(
    new BluePrintChainFilter(
      BluePrintChainDirection.Up,
      engine.GetSession()
    )
  ).LastOrDefault();

The solution is to find a top-most localized item's parent first as per Frank's recipe:

return
  ((RepositoryLocalObject)engine
    .GetObject(
      TemplateUtilities.CreateTcmUriForPublication(
        item.OwningRepository.Id.ItemId,
        item.Id
      )
    )
  ).GetBluePrintChain(
    new BluePrintChainFilter(
      BluePrintChainDirection.Up,
      engine.GetSession()
    )
  ).LastOrDefault();
like image 3
esteewhy Avatar answered Nov 13 '22 20:11

esteewhy