9

I want to display youtube or vimeo videos on a page.

I already created a specific schema and a component template so that the user can add the videos to a page via the component presentations of the page. This is working perfectly.

The dreamweaver component template looks like:

<!-- TemplateBeginIf cond="Provider == 'YouTube'" -->
        <iframe id="ytplayer" type="text/html" width="@@Width@@" height="@@Height@@" src="http://www.youtube.com/embed/@@VideoID@@" frameborder="0"/>
<!-- TemplateEndIf -->

<!-- TemplateBeginIf cond="Provider == 'Vimeo'" -->
        <iframe src="http://player.vimeo.com/video/@@VideoID@@" width="@@Width@@" height="@@Height@@" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
<!-- TemplateEndIf -->

But the goal is that a user can add a link to a video component in the wysiwyg-editor. That way it is possible to have text - video - more text.

So the idea was tho create a custom linkresolver.
I have already the logic to get all the links and to check if they are linking to a component with a certain type. But I'm stuck on how I can replace the link with a component presentation based on a fixed component template.

Edit: I did some modifications and the code of the linkresolver is now:

XmlDocument domOutput = output.GetAsXmlDocument();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("tridion", "http://www.tridion.com/ContentManager/5.0");
if (domOutput != null)
{
    Logger.Debug("domOutput is not null");
    foreach (XmlNode nodeCompLink in domOutput.SelectNodes("//a[@tridion:href]", nsmgr))
    {
        String uriCompLink = nodeCompLink.Attributes["href", "http://www.tridion.com/ContentManager/5.0"].Value;
        try
        {
            Component linkedComponent = (Component)engine.GetObject(uriCompLink);

                    String title = linkedComponent.Schema.Title.ToLower();
                    Logger.Debug("Title: " + title);
                    if (title == "video")
                    {
                        string comPressentation = engine.RenderComponentPresentation(linkedComponent.Id, new global::Tridion.ContentManager.TcmUri("tcm:66-72075-32"));
                        Logger.Debug("comPressentation: " + comPressentation);
                        XmlDocument tempDoc = new XmlDocument();
                        tempDoc.LoadXml(comPressentation);
                        XmlNode tempNode = tempDoc.DocumentElement;

                        //change nodecomplink with component pressentation
                        Logger.Debug("insert component pressentation");
                        nodeCompLink.ParentNode.InsertAfter(domOutput.ImportNode(tempNode, true), nodeCompLink);

                        //remove nodecomplink
                        Logger.Debug("remove link");
                        nodeCompLink.ParentNode.RemoveChild(nodeCompLink);


                    }

        }
        catch (Exception e)
        {
            Logger.Error("There is an error: " + e.Message);
        }
    }
    output.SetAsString(domOutput.OuterXml);
}

In template builder my link is correctly replaced but I still have 2 issues that I need to resolve:

  1. For Vimeo the componentpressentation don't seems to be valid xml => continue to investigate
  2. When publishing the link is not replaced with the content of the component pressentation. => solution: changing the component template to a dynamic component template and republishing the page.
  • If it works in Template Builder, but not when publishing then you could try turning on logging for the Publisher (done in the MMC Snap-in) to see where it is getting to in your code. Remember to turn it off though as it affects performance. If it is not working in Template Builder then you could check the logs in there or enable remote debugging. – Jonathan Williams May 8 '13 at 13:12
4

I would probably do this using templating code rather than a Custom Resolver.

If you take a look at the source of the 'Process Download Links In Output' eXtension, (available in the downloadable ZIP) then it should help you to:

  1. Parse the content of the Component (available as the 'output' in the package),
  2. Update the output to include the HTML for your video (using the RenderComponentPresentation(componentTcmId, componentTemplateTcmId) method probably), and
  3. Add the binary for your video to the package to make sure that it gets published.

If you are using the Razor Mediator, then you may be able to do all of this in a helper function, rather than a C# TBB.

  • Actually I try to do it already like in the eXtension you mention. The confusion is probably because of the link I placed in my question to the Custom Resolver example (tridiondeveloper.com/a-custom-resolver-in-practice). I used the "old" code on that page to get the links from the content. I will see if I can call RenderComponentPressentation in my visual studio TBB. – Glenn Franquet May 8 '13 at 11:40
2

This is working now for me.

My videos are rendered perfectly by using following things:

  1. A schema video with fields VideoId, Provider (YouTube, Vimeo), width and height

  2. A dreamweaver component template with following code

  3. A component template Video CT is set to "Published as Dynamic Component"

  4. A building block CustomLinkResolver for the .Net Assembly with following code in the Transform function

try { Logger.Debug("Looking for component links"); Item output = package.GetByName("Output");

Initialize(engine, package); Publication p = GetPublication();

XmlDocument domOutput = output.GetAsXmlDocument();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("tridion", "http://www.tridion.com/ContentManager/5.0");
if (domOutput != null)
{
    Logger.Debug("domOutput is not null");
    foreach (XmlNode nodeCompLink in domOutput.SelectNodes("//a[@tridion:href]", nsmgr))
    {
        String uriCompLink = nodeCompLink.Attributes["href", "http://www.tridion.com/ContentManager/5.0"].Value;
        try
        {
            Component linkedComponent = (Component)engine.GetObject(uriCompLink);

                    String title = linkedComponent.Schema.Title.ToLower();
                    Logger.Debug("Title: " + title);
                    if (title == "video")
                    {
                        //We don't want to use hardcoded tcm-ids so we use a webdavurl (ex: /Building%20Blocks/System/Component%20Templates/Video%20CT.tctcmp)
                        IdentifiableObject identifiableObject = engine.GetObject(p.WebDavUrl + Constants.COMPONENTTEMPLATEWEBDAVPATH_VIDEO);
                        if (identifiableObject != null)
                        {
                            global::Tridion.ContentManager.TcmUri videotemplate = identifiableObject.Id;
                            Logger.Debug("videotemplate: " + videotemplate);

                            //Get the component presentation for the component and template
                            string comPressentation = engine.RenderComponentPresentation(linkedComponent.Id, videotemplate);
                            Logger.Debug("comPressentation: " + comPressentation);
                            XmlDocument tempDoc = new XmlDocument();
                            tempDoc.LoadXml(comPressentation);
                            XmlNode tempNode = tempDoc.DocumentElement;

                            //change nodecomplink with component pressentation
                            Logger.Debug("insert component pressentation");
                            nodeCompLink.ParentNode.InsertAfter(domOutput.ImportNode(tempNode, true), nodeCompLink);

                            //remove nodecomplink
                            Logger.Debug("remove link");
                            nodeCompLink.ParentNode.RemoveChild(nodeCompLink);
                        }
                        else
                            Logger.Error("template not found: " + p.WebDavUrl + Constants.COMPONENTTEMPLATEWEBDAVPATH_VIDEO);
                    }          
        }
        catch (Exception e)
        {
            Logger.Error("There is an error: " + e.Message);
        }
    }
    output.SetAsString(domOutput.OuterXml);
}

} catch (Exception e) { Logger.Error(e.Message); }

Remark: We are using some helper classes that are not included in this code example but at least this gives a good idea how to replace component links with specific component presentations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.