Links and references between cloned items in Sitecore 6.4
Asked Answered
P

1

16

I'm building a data repository site that I will then clone in its entirety to provide multiple clone sites, enabling localistaion of global content.

What I need to do is to ensure that all references between items in the repository site (links in rich text fields, item references to pull in "related items" spots etc) are overridden to refer to the relevant clones instead of the original items in the repository.

This will likely involve e.g. customising the LinkManager and maybe GetItem(itemID) with some additional logic to find the correct clone.

What I need to know is which bits of the API do I need to worry about? Is there a single modification I can make which will inherit to link rendering in a rich text field in .Net components, item references fed to a sublayout from drop list, renderings through XSLT etc? I need an item ID to work as an alias for its clone when in the context of the clone site. Context.Database.GetItem(ID) needs to return a clone when in the clone site context.

I'm basically looking for a mechanism that will translate "Data/Home/Products/Product A" to "clone/Home/Products/ProductA" whenever and however I use it in the context of a clone site.

Where do I need to implement this logic, how many places?

Cross posted to SDN http://sdn.sitecore.net/SDN5/Forum/ShowPost.aspx?PostID=35598

This is related to an earlier question Handling internal links in Sitecore 6.4 cloned sites , but contains more detail and is more specific.

EDIT: though the ideal solution would place this functionality deep within Sitecore it is important that this only applies to content as viewed on the actual website, i.e. it must not interfere with Sitecore pipelines for e.g. creating, cloning and deleting items.

Penna answered 12/5, 2011 at 13:22 Comment(5)
So for each cloned site you would then create a new <site> def'n in the web.config for it? I haven't done much with this so I'm curious about your process.Cyclosis
Yes, each site will have its own domain (www.example.com, www.example.co.uk etc.) and a site node in the web.config. The idea is to be able to push content to local subsidiares but give them control over localisation. We don't want a manual process of changing all references to be internal to the clone site and we don't want to break inheritance from the data repository.Penna
The info I'm looking for is where in sitecore are references between items determined. Relative Xpaths are fine, as the content structure isn't likely to vary much between data repository and clone, but any reference stored as a GUID needs to be interpretted and possibly overridden. It's possible that we'd need to build alternative mechanisms for e.g. GetItem and then recode but really I just want to plug in something that will do the work in one place.Penna
Have you seen this Item Mirroring code blog.capaxsolutions.co.uk/2010/06/09/…? It is not exactly what you are asking for but it might give you a few ideas about what you need to modify.Mazzola
Thanks James, there's some interesting code there.Penna
T
3

I recommend you take a different approach. Rather than changing the links themselves, you can add code to the HttpRequestPipeline to resolve "Data/Home/Products/Product A" as "clone/Home/Products/ProductA". A similar approach is described in Reusing and Sharing Data:

A CMS user could use the Rich Text Editor, rendering properties, or other features to link to an item based on an item selection data template. Account for these conditions in your code. You can configure an httpRequestBegin pipeline processor to handle HTTP requests for items [...]

To apply this approach to your scenario, add the custom implementation of HttpRequestProcessor after <processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel"/> in the HttpRequestBegin pipeline in web.config.

Here's the logic to implement:

  1. Use HttpContext.Current.Request.UrlReferrer to determine the referring site.
  2. Verify that the referring site is in your list of cloned sites.
  3. Check if Sitecore.Context.Item is in the source site.
  4. Create a string with the new path, and verify that this item exists using Database.GetItem().
  5. Modify Sitecore.Context.Item to the new item.

The advantage of this approach is that you do not need to intercept the many ways that a link can be created, and you keep your path rewriting logic in one place. In effect, you will be creating an alias from "Data/Products/ProductA" to "clone/Home/ProductA" that will only take effect if your site is in your list of clones.

Update: I did a test of this approach in Office Core. I created a second site, AlternalteSite, with a child node Our-Process. The AlternateSite home page has a link to /home/Our-Process. When the code below is added to the HttpRequestBegin pipeline, the link directs to the /AlternateSite/Our-Process item.

public class SiteChanger : HttpRequestProcessor
 {
   // Some definitions removed...
    public override void Process(HttpRequestArgs args)
    {

        if (ReferringSiteIsTarget())
        {
            Item targetItem = GetTargetItem();
            if (targetItem != null)
            {
                Sitecore.Context.Item = targetItem;
            }
        }
    }

    private Item GetTargetItem()
    {
        string currentItemPath = Sitecore.Context.Item.Paths.FullPath;
        string newPath;

        if (currentItemPath.Contains(SourcePath))
        {
            newPath = currentItemPath.Replace(SourcePath, TargetPath);
            return Sitecore.Context.Database.GetItem(newPath);
        }
        return null;
    }
}

Update2: As James Walford points out in the comments, this approach only works if the clones are not renamed. Sitecore does not, to my knowledge, provide a way of traversing from a source item to its clones in the web database. In master, you can use the Link Database to get from an item to its clones (see this forum post by John West), but after publication, clones become normal items, so presumably will not be included in the Link Database.

One approach would be to add a multilist of links to clones to the standard template, and add logic to populate this as part of the uiCloneItems pipeline, and to use this data in the HttpRequestProcessor code. This will preserve the Link Database relationship, but will put overhead on both the cloning process and the Http Request resolution process, as your code would need to iterate through all the clones to determine which one lived in the requesting website.

Thong answered 22/1, 2012 at 16:30 Comment(4)
Hi @DanSolovay That works fine for generating links during item processing, and we implemeted somethig similar (though we thought we had some side affects so removed it again), but we also need to ensure item references to data that should be included during processing that isn't going to be rendered as a link but are consumed by the rendering - e.g. a list view populated with metadata keyword items. These are never addressed directly by an http request. cont below...Penna
We'd also prefer to avoid relying on a relative path comparison if possible, as we'd like to be able to rename clones to suit their specific local contexts. I've marked the answer as helpful as I think it deserves credit, but it's not quite the full answer - yet!Penna
@JamesWalford, renaming of links is a difficult issue, since the relationship between clone and source does not persist in the web database. The metadata issue probably goes beyond what clones are designed to do. Normally, you would modify the clone to change the metadata links--it sounds like you want the clone to have different metadata values from its source while still being unmodified.Thong
Yes, that's exactly what we want to do. It's not just metadata, there are various other bits of data that can't really be scoped as global for the parent site and all clones but are general enough that they'll be the same values across all sites.Penna

© 2022 - 2024 — McMap. All rights reserved.