cakephp/cakephp

Enhance TextHelper autoLinkUrls()

dereuromark opened this issue · 4 comments

Description

Currently, the Text helper autoLink()/autoLinkUrls() are pretty hardcoded in the way they finalize the link.
In my case, I needed a way to at least use an outbound controller as redirect mechanism.

I whipped sth up as extension:
https://github.com/dereuromark/cakephp-tools/blob/e3dc4b48be3aca38eca481192da4706f5c285a88/src/View/Helper/TextHelper.php#L163-L198

My question would be: What parts would make sense to add to the core in 5.1?

Callback for inverted control

$text = 'Text www.domain.test?id=2&sub=3 and more';

$that = $this->Text;
$callable = function (string $link, string $url, array $options) use ($that) {
	$linkOptions = $options;

	$linkOptions['target'] = '_blank';
	$linkOptions['rel'] = 'nofollow';
	// Call a helper method on the same helper
	$link = $that->prepareLinkName($link, $options);
	$url = ['controller' => 'Outbound', 'action' => 'redirect', '?' => ['url' => $url]];

	return $that->Html->link($link, $url, $linkOptions);
};

echo $this->Text->autoLinkUrls($text, ['callable' => $callable]);

Resulting in

Text <a href="/outbound/redirect?url=http%3A%2F%2Fwww.domain.test%3Fid%3D2%26sub%3D3" target="_blank" rel="nofollow">www.domain.test?id=2&amp;sub=3</a> and more

Link name preparations

As shown above, the link can have some improvements too, this could be directly built into the _linkUrls() method:

// strip protocol if desired (default)
if (!isset($options['stripProtocol']) || $options['stripProtocol'] !== false) {
	$link = $this->stripProtocol($link);
}
if (!isset($options['maxLength'])) {
	$options['maxLength'] = 50; # should be long enough for most cases
}
// shorten display name if desired (default)
if (!empty($options['maxLength']) && mb_strlen($link) > $options['maxLength']) {
	$link = mb_substr($link, 0, $options['maxLength']);
	$link .= $options['ellipsis'] ?? '…';
}

Outputs long links more useful as

<a href="http://www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer-werwerwe-werwerwer-werwerdfrffsd-werwer">
www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-w…
</a>

Long names can often break the text flow on pages, so the shortening here insight is quite useful. The protocol strip makes the main domain and URL part more visible, protocol is not sth needed for the link itself usually.

We can default those to either false by default or enable them by default as best practice.

CakePHP Version

5.1

Callback for inverted control

Would this callback be registered with the helper as a configuration option? It seems awkward to need to provide a callback to each block of text that is formatted.

I think the proposed options for controlling the length of links are straightforward includes. For backwards compatibility we would need to default the maxLength to null/undefined as to not alter the formatting done in sites today.

So far there is no usage of $this->config() yet in this helper.
Both is possible.
I think it is fine to have a global one that could be overwritten.
But when I want to have a specific behavior only for a subset of calls, a custom callback for each block can be useful and a global one would modify too many other ones even on totally different actions.

Part 2 open

I dont exactly know how the Invert of Control could be implemented.
Also, if we can make this more global, e.g. using helper wide config as defaults.

For now, I think people can use extension and _linkUrls() overwrite if needed.

So for me, it is ok as such, I can close then.