How can I accomplish: <xen:if is="{$requestPaths.requestUri} CONTAINS 'something'">


Well-known member
As the title states, I'd really like to be able to have a conditional that checks if the requestPaths.requestUri contains a certain string anywhere in the variable. What's the easiest way to do so?

For my use case, checking for an explicit URL fails in some cases (because there can be a query string attached to the URL, which makes it not match the conditional).

I just want to do something like:
<xen:if is="{$requestPaths.requestUri} CONTAINS 'conversations'">

Many thanks for any advice or insights.


You can't do it directly in templates. But if you create a template via a listener (hook or post render) it's easy.
But why do you want to check the URL contains a specific word ? If it's to target a precise page or forum area you can use the controller or view variables (check in the dev question area, the thread should be at the top ; sorry I'm on my mobile now). You case use those variables directly in templates :
{$controllerName} or {$controllerAction} or {$viewName} , check the spelling I'm not sure.
Can I insert a PHP fragment in the template to do it? _any_ easy hack-ish way would save me a lot of time at this point. :D

I've tried using $contentTemplate, $controllerName, etc... but they seem to be ignored, despite showing up correctly with <xen:helper dump...

The base problem I'm trying to solve is as follows:
I want visitors to be able to start a conversation with anyone in a thread by simply clicking on their name. I've modified their username links in message_user_info template to form the link:
<xen:if is="{$visitor.user_id} AND {$user.user_id} != {$visitor.user_id}">
  <a class="username userText" href="{xen:link conversations/add, '', 'to={$user.username}'}">
  <xen:username user="$user" class="userText" itemprop="name" rich="true" />

I'm calling the conversation_add template via an OverlayTrigger link. It's working great, except that the overlay initialises the richtext editor, which means you end up with doubled-up editors in the quick reply editor (that's already on the bottom of the page).

I only need the textarea editor when I'm calling conversation_add as an overlay. I've tried a whole bunch of conditionals in various places that seem ignored (due to template includes/nesting order? who knows).

In the conversation_add template, my work-around was to make this mod where the editor is called:
<xen:if is="{$requestPaths.requestUri} == '/conversations/add'">
    {xen:raw $editorTemplate}
    <xen:hook name="editor" params="{xen:array 'editorId={$editorId}'}">
        <div class="editorPadding">
            <textarea name="{$formCtrlName}" id="{$editorId}" class="textCtrl MessageEditor" style="{xen:if $height, 'height: {$height};'}">{$message}</textarea>
            <input type="hidden" name="_xfRelativeResolver" value="{$requestPaths.fullUri}" />

Now, this actually solves all of the issues, except when someone adds a conversation via the traditional way:

This fails the {$requestPaths.requestUri} conditional because of the querystring on the end. If I could have it ignore that string, it would be finished :)

Hope that makes sense!

Also, please keep in mind I'm not a programmer. I have a designers brain and fail at this sort of stuff. Since it's a personal project, I'm stuck with it :)

I didn't know there were different kind of brains ;)

Well I've looked at your code and the problem is going to be the... editor as you've already seen. You can't call like this an editor and you can't neither include the editor template (there are too many variables to set and that are not available in the conversation template). So this part of your code will not work
textarea name="{$formCtrlName}" id="{$editorId}" class="textCtrl MessageEditor" style="{xen:if $height, 'height: {$height};'}">{$message}</textarea>
If you use the classic variable $editorTemplate, the new editor is inserted below the previous one; may be because they share the same id, I'm not sure, I haven't check further since there is an id conflict.

Your designer blood is not going to like the following part:
What you should test is:
  • create a listener for the controller public
  • extend the class XenForo_ControllerPublic_Conversation
  • create a new action "actionAddWithOverlay" that will duplicate this one "public function actionAdd()" with the same code (you might not need all of this, but never mind) but with a new View and Template parameters inside the last return:
    return $this->responseView('XenForo_ViewPublic_Conversation_AddWithOverlay', 'conversation_add_with_overlay', $viewParams);
  • Then you can create the file AddWithOverlay.php inside the directory: XenForo/ViewPublic/Conversation
    You can copy most of the code from Add.php and add, finally, add a new variable to setup the ID of the editor
class XenForo_ViewPublic_Conversation_AddWithOverlay extends XenForo_ViewPublic_Base
    public function renderHtml()
        $this->_params['editorTemplate'] = XenForo_ViewPublic_Helper_Editor::getEditorTemplate(
            $this, 'message',
            array('editorId' => 'MyBelovedEditorId)

  • Then create the template 'conversation_add_with_overlay' with the code you want (use the one from "'conversation_add" and modify it from there
  • And finally go back to your original code with the overlay trigger (oh you forgot to add it by the way - if I don't add it on my dev board I've got a js error with an addon of another developer) AND with the new controller action you create before "addWithOverlay":
  <a class="username userText OverlayTrigger" href="{xen:link conversations/addWithOverlay, '', 'to={$user.username}'}">

Now all of this is theory, I didn't try it and it certainly needs some debugging.
The good thing then is you will not have to bother any more with any conditional.

Might the force be with you
That's an excellent answer Cédric, thank you for writing it out.

I've read it a few times... I'll attempt this soon and see what happens.
Top Bottom