Skip to content

Commit

Permalink
[FEATURE] Add a telephone (tel:) link handler
Browse files Browse the repository at this point in the history
The new link handler allows you to set links
in a new tab in the link browser to
phone numbers using the tel: protocol.

Resolves: #86629
Releases: master
Change-Id: I1a69fefbe16db9aaae51abfd80f154fa6aa8791a
Reviewed-on: https://review.typo3.org/58674
Reviewed-by: Jan Helke <typo3@helke.de>
Tested-by: Jan Helke <typo3@helke.de>
Tested-by: TYPO3com <noreply@typo3.com>
Reviewed-by: Jörg Bösche <typo3@joergboesche.de>
Tested-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Reviewed-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
  • Loading branch information
runepiper authored and maddy2101 committed Jan 11, 2019
1 parent bbea0b4 commit d19ec27
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 1 deletion.
Expand Up @@ -73,6 +73,9 @@ public function resolve(string $linkParameter): array
} elseif (GeneralUtility::validEmail(parse_url($linkParameter, PHP_URL_PATH))) {
$result['type'] = LinkService::TYPE_EMAIL;
$result['email'] = $linkParameter;
} elseif (strpos($linkParameter, 'tel:') === 0) {
$result['type'] = LinkService::TYPE_TELEPHONE;
$result['telephone'] = $linkParameter;
} elseif (strpos($linkParameter, ':') !== false) {
// Check for link-handler keyword
list($linkHandlerKeyword, $linkHandlerValue) = explode(':', $linkParameter, 2);
Expand Down
4 changes: 4 additions & 0 deletions typo3/sysext/core/Classes/LinkHandling/LinkService.php
Expand Up @@ -29,6 +29,7 @@ class LinkService implements SingletonInterface
const TYPE_PAGE = 'page';
const TYPE_URL = 'url';
const TYPE_EMAIL = 'email';
const TYPE_TELEPHONE = 'telephone';
const TYPE_FILE = 'file';
const TYPE_FOLDER = 'folder';
const TYPE_RECORD = 'record';
Expand Down Expand Up @@ -120,6 +121,9 @@ public function resolveByStringRepresentation(string $urn): array
} elseif (stripos($urn, 'mailto:') === 0 && $this->handlers[self::TYPE_EMAIL]) {
$result = $this->handlers[self::TYPE_EMAIL]->resolveHandlerData(['email' => $urn]);
$result['type'] = self::TYPE_EMAIL;
} elseif (stripos($urn, 'tel:') === 0 && $this->handlers[self::TYPE_TELEPHONE]) {
$result = $this->handlers[self::TYPE_TELEPHONE]->resolveHandlerData(['telephone' => $urn]);
$result['type'] = self::TYPE_TELEPHONE;
} else {
$result = [];
if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['Link']['resolveByStringRepresentation'] ?? null)) {
Expand Down
48 changes: 48 additions & 0 deletions typo3/sysext/core/Classes/LinkHandling/TelephoneLinkHandler.php
@@ -0,0 +1,48 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Core\LinkHandling;

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

/**
* Resolves telephone numbers
*/
class TelephoneLinkHandler implements LinkHandlingInterface
{

/**
* Returns the link to a telephone number as a string
*
* @param array $parameters
* @return mixed
*/
public function asString(array $parameters): string
{
$telephoneNumber = preg_replace('/(?:[^\d\+]+)/', '', $parameters['telephone']);

return 'tel:' . $telephoneNumber;
}

/**
* Returns the telephone number without the "tel:" prefix
* in the 'telephone' property of the array.
*
* @param array $data
* @return array
*/
public function resolveHandlerData(array $data): array
{
return ['telephone' => substr($data['telephone'], 4)];
}
}
2 changes: 2 additions & 0 deletions typo3/sysext/core/Configuration/DefaultConfiguration.php
Expand Up @@ -323,6 +323,7 @@
'url' => \TYPO3\CMS\Core\LinkHandling\UrlLinkHandler::class,
'email' => \TYPO3\CMS\Core\LinkHandling\EmailLinkHandler::class,
'record' => \TYPO3\CMS\Core\LinkHandling\RecordLinkHandler::class,
'telephone' => \TYPO3\CMS\Core\LinkHandling\TelephoneLinkHandler::class,
],
'livesearch' => [], // Array: keywords used for commands to search for specific tables
'formEngine' => [
Expand Down Expand Up @@ -1314,6 +1315,7 @@
'url' => \TYPO3\CMS\Frontend\Typolink\ExternalUrlLinkBuilder::class,
'email' => \TYPO3\CMS\Frontend\Typolink\EmailLinkBuilder::class,
'record' => \TYPO3\CMS\Frontend\Typolink\DatabaseRecordLinkBuilder::class,
'telephone' => \TYPO3\CMS\Frontend\Typolink\TelephoneLinkBuilder::class,
'unknown' => \TYPO3\CMS\Frontend\Typolink\LegacyLinkBuilder::class,
],
'passwordHashing' => [
Expand Down
@@ -0,0 +1,18 @@
.. include:: ../../Includes.txt

=============================================================
Feature: #86629 - Implement LinkHandler for telephone numbers
=============================================================

See :issue:`86629`

Description
===========

A new phone number link handler has been added.

With this new link handler you can set links in a new tab in the link browser to phone numbers using the `tel:` protocol.

A valid phone number consists of only numbers and the + character.

.. index:: Backend, Frontend
102 changes: 102 additions & 0 deletions typo3/sysext/core/Tests/Unit/LinkHandling/TelephoneLinkHandlerTest.php
@@ -0,0 +1,102 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Core\Tests\Unit\LinkHandling;

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

use TYPO3\CMS\Core\LinkHandling\TelephoneLinkHandler;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;

/**
* Class TelephoneLinkHandlerTest
*/
class TelephoneLinkHandlerTest extends UnitTestCase
{

/**
* Data to resolve strings to arrays and vice versa, external, mail, page
*
* @return array
*/
public function resolveParametersForNonFilesDataProvider(): array
{
return [
'telephone number with protocol' => [
[
'telephone' => 'tel:012345678'
],
[
'telephone' => '012345678'
],
'tel:012345678'
],
'telephone number with protocol and spaces' => [
[
'telephone' => 'tel:+49 123 45 56 78'
],
[
'telephone' => '+49 123 45 56 78'
],
'tel:+49123455678'
],
'invalid telephone number' => [
[
'telephone' => 'tel:+43-hello-world'
],
[
'telephone' => '+43-hello-world'
],
'tel:+43'
],
'telephone number with weird characters' => [
[
'telephone' => 'tel:+43/123!45&56%78'
],
[
'telephone' => '+43/123!45&56%78'
],
'tel:+43123455678'
],
];
}

/**
* @test
*
* @param array $input
* @param array $expected
*
* @dataProvider resolveParametersForNonFilesDataProvider
*/
public function resolveReturnsSplitParameters($input, $expected): void
{
$subject = new TelephoneLinkHandler();
$this->assertEquals($expected, $subject->resolveHandlerData($input));
}

/**
* @test
*
* @param string $input
* @param array $parameters
* @param string $expected
*
* @dataProvider resolveParametersForNonFilesDataProvider
*/
public function splitParametersToUnifiedIdentifier($input, $parameters, $expected)
{
$subject = new TelephoneLinkHandler();
$this->assertEquals($expected, $subject->asString($parameters));
}
}
30 changes: 30 additions & 0 deletions typo3/sysext/frontend/Classes/Typolink/TelephoneLinkBuilder.php
@@ -0,0 +1,30 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Frontend\Typolink;

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

/**
* Builds a TypoLink to a telephone number
*/
class TelephoneLinkBuilder extends AbstractTypolinkBuilder
{
/**
* @inheritdoc
*/
public function build(array &$linkDetails, string $linkText, string $target, array $conf): array
{
return [$linkDetails['typoLinkParameter'], $linkText];
}
}
107 changes: 107 additions & 0 deletions typo3/sysext/recordlist/Classes/LinkHandler/TelephoneLinkHandler.php
@@ -0,0 +1,107 @@
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Recordlist\LinkHandler;

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Link handler for telephone links
* @internal This class is a specific LinkHandler implementation and is not part of the TYPO3's Core API.
*/
class TelephoneLinkHandler extends AbstractLinkHandler implements LinkHandlerInterface
{
/**
* Parts of the current link
*
* @var array
*/
protected $linkParts = [];

/**
* We don't support updates since there is no difference to simply set the link again.
*
* @var bool
*/
protected $updateSupported = false;

/**
* Constructor
*/
public function __construct()
{
parent::__construct();
// remove unsupported link attributes
foreach (['target', 'rel'] as $attribute) {
$position = array_search($attribute, $this->linkAttributes, true);
if ($position !== false) {
unset($this->linkAttributes[$position]);
}
}
}

/**
* Checks if this is the handler for the given link
*
* The handler may store this information locally for later usage.
*
* @param array $linkParts Link parts as returned from TypoLinkCodecService
*
* @return bool
*/
public function canHandleLink(array $linkParts): bool
{
if (isset($linkParts['url']['telephone'])) {
$this->linkParts = $linkParts;
return true;
}
return false;
}

/**
* Format the current link for HTML output
*
* @return string
*/
public function formatCurrentUrl(): string
{
return $this->linkParts['url']['telephone'];
}

/**
* Render the link handler
*
* @param ServerRequestInterface $request
*
* @return string
*/
public function render(ServerRequestInterface $request): string
{
GeneralUtility::makeInstance(PageRenderer::class)->loadRequireJsModule('TYPO3/CMS/Recordlist/TelephoneLinkHandler');

$this->view->assign('telephone', !empty($this->linkParts) ? $this->linkParts['url']['telephone'] : '');
return $this->view->render('Telephone');
}

/**
* @return string[] Array of body-tag attributes
*/
public function getBodyTagAttributes(): array
{
return [];
}
}
Expand Up @@ -30,6 +30,9 @@
<trans-unit id="email">
<source>Email</source>
</trans-unit>
<trans-unit id="telephone">
<source>Telephone</source>
</trans-unit>
<trans-unit id="special">
<source>Special</source>
</trans-unit>
Expand Down Expand Up @@ -84,6 +87,9 @@
<trans-unit id="emailAddress">
<source>Email address</source>
</trans-unit>
<trans-unit id="telephoneNumber">
<source>Telephone number</source>
</trans-unit>
<trans-unit id="setLink">
<source>Set Link</source>
</trans-unit>
Expand Down
@@ -0,0 +1,19 @@
<div class="element-browser-panel element-browser-main">
<div class="element-browser-main-content">
<div class="element-browser-body">
<form action="" id="ltelephoneform" class="form-horizontal">
<div class="form-group form-group-sm">
<label class="col-xs-4 control-label"><f:translate key="LLL:EXT:recordlist/Resources/Private/Language/locallang_browse_links.xlf:telephoneNumber" /></label>
<div class="col-xs-8">
<div class="input-group">
<input type="tel" name="ltelephone" size="20" class="form-control" value="{telephone}" />
<div class="input-group-btn">
<input class="btn btn-sm btn-default" type="submit" value="{f:translate(key: 'LLL:EXT:recordlist/Resources/Private/Language/locallang_browse_links.xlf:setLink')}" />
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>

0 comments on commit d19ec27

Please sign in to comment.