Wednesday, January 19, 2022

TYPO3 - Multiple dynamic parameters for a typolink using a custom userFunc

I often use the TYPO3 linkHandler to enable the possibility for editors to create direct links to records from within the CKEditor in TYPO3 backend. This is all well documented and easy to configure using the RecordLinkHandler, as long as the resulting link only contains one dynamic parameter. But sometimes it may be required to have multiple dynamic parameters for the resulting link. In this case you may need to create a userFunc for the typolink function in order to create a custom configuration which uses multiple dynamic parameters.

Requirement

Let us assume, you have an event which has multiple event registrations. Registrations are listed in the detail view of an event and each registration is shown as an accordion item with a unique ID in markup. Now you want to create a link to an event and set a link anchor to a specific registration. The resulting URL should be as shown below:

https://www.cool-events.tld/events/my-first-event#registration-1

Calling the URL will open the event detail page and scroll down the the HTML element with the ID "registration-1".

Note: This is just an example, which also can be achieved without a custom userFunc. Goal of this article is to demonstrate how to use a userFunc for typolink.

Solution

In order to archive the requirement, first a linkHandler Page TSConfig must be created as shown below:


TCEMAIN.linkHandler {
    event {
        handler = TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler
        label = Event Registration
        configuration {
            table = tx_sfeventmgt_domain_model_registration
        }
    }
}

Next, the TypoScript for the link generation is added. 


config {
  recordLinks {
    registration {
      typolink {
        parameter = 1
        userFunc = DERHANSEN\SfEventMgt\UserFunc\TypoLink->createEventLink
        userFunc {
          eventUid = TEXT
          eventUid.data = field:event
          registrationUid = TEXT
          registrationUid.data = field:uid
        }
      }
    }
  }
}

Finally a custom userFunc needs to be created which renders the A-tag for the link.


<?php

declare(strict_types=1);

namespace DERHANSEN\SfEventMgt\UserFunc;

use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

class TypoLink
{
    private const EVENT_DETAILPID = 22;

    public ContentObjectRenderer $cObj;

    public function createEventLink(array $content, array $config): string
    {
        $eventUid = $this->cObj->cObjGetSingle($config['eventUid'], $config['eventUid.']);
        $registrationUid = $this->cObj->cObjGetSingle($config['registrationUid'], $config['registrationUid.']);

        // Link parameters (can also contain multiple dynamic parameters)
        $parameters = [
            'tx_sfeventmgt_pieventdetail' => [
                'controller' => 'Event',
                'action' => 'detail',
                'event' => $eventUid,
            ]
        ];

        $link = $this->cObj->typoLink($this->cObj->lastTypoLinkResult->getLinkText(), [
            'parameter' => self::EVENT_DETAILPID,
            'additionalParams' => '&' . http_build_query($parameters),
            'section' => 'registration-' . $registrationUid,
            'returnLast' => 'url',
        ]);

        return '<a href="' . $link . '">';
    }
}

The most important part is, that the custom userFunc must only return the opening A-tag. In the userFunc, it is basically possible to construct the resulting link however you want. In the example above, 2 dynamic parameters are used in the function ($eventUid and $registrationUid). It is of course also possible to e.g. do dynamic database lookups in the function to fetch other dynamic parameters required for link construction.