Problem/Motivation
As detected by #2484693: Telephone Link field formatter InvalidArgumentException with 5 digits or fewer in the number, PHP does not guarantee the parse_url
function results for URIs.
The problem is that PHP's parse_url is 'designed' for url's not for URIs.
Because by documentation parse_url:
This function is intended specifically for the purpose of parsing URLs and not URIs.
That can lead to many issues as this function is widely used in the Core as shown in the following table:
The ones which work:
File/Class | Function/Method | Result |
---|---|---|
core/includes/batch.inc | _batch_finished | OK |
core/includes/install.core.inc | install_check_translations | OK |
core/includes/install.core.inc | install_retrieve_file | OK |
\Drupal\Component\Utility\UrlHelper | externalIsLocal | OK |
\Drupal\Component\Utility\UrlHelper | parse | OK |
\Drupal\Core\DrupalKernel | initializeRequestGlobals | OK |
\Drupal\Core\Database\Database | convertDbUrlToConnectionInfo | OK |
\Drupal\Core\Utility\UnroutedUrlAssembler | assemble | OK |
\Drupal\language\Form\NegotiationUrlForm | validateForm | OK |
\Drupal\language\Plugin \LanguageNegotiation\LanguageNegotiationUrl | getLangcode | OK |
\Drupal\language\Tests \LanguageUILanguageNegotiationTest | testLanguageDomain | OK |
\Drupal\language\Tests\LanguageUrlRewritingTest | testDomainNameNegotiationPort | OK |
\Drupal\link\Plugin\Field\FieldWidget\LinkWidget | getUriAsDisplayableString | OK |
\Drupal\menu_link_content\Entity\MenuLinkContent | preSave | OK |
\Drupal\node\Tests\PagePreviewTest | testPagePreview | OK |
\Drupal\search\Tests\SearchLanguageTest | testLanguages | OK |
\Drupal\simpletest\BrowserTestBase | getAbsoluteUrl | OK |
\Drupal\simpletest\BrowserTestBase | setUp | OK |
\Drupal\simpletest\WebTestBase | getAbsoluteUrl | OK |
\Drupal\system\Tests\Form\RebuildTest | testPreserveFormActionAfterAJAX | OK |
\Drupal\system\Tests\Pager\PagerTest | testActiveClass | OK |
\Drupal\system\Tests\Pager\PagerTest | testPagerQueryParametersAndCacheContext | OK |
core/modules/update/update.manager.inc | update_manager_file_get | OK |
\Drupal\views\Plugin\views\display\PathPluginBase | validatePath | OK |
\Drupal\views\Plugin\views\field\FieldPluginBase | renderAsLink | OK |
\Drupal\views_ui\ViewEditForm | getDisplayDetails | OK |
Not OK:
\Drupal\Core\Url | fromUri | Not OK (see the issue summary) |
\Drupal\Core\Validation\Plugin\Validation \Constraint\PrimitiveTypeConstraintValidator | validate | Not OK |
\Drupal\link\Plugin\Field\FieldWidget\LinkWidget | getUserEnteredStringAsUri | Not OK (it transforms tel:xxx to internal:tel:xxx) |
\Drupal\link\Plugin\Field\FieldWidget\LinkWidget | validateUriElement | Not OK (partly because of getUserEnteredStringAsUri) |
\Drupal\link\Plugin\Validation \Constraint\LinkExternalProtocolsConstraintValidator | validate | Not OK (for both tel:911 [error], tel:65536 [error] and tel:0123456789 [failure]) |
\Drupal\menu_link_content \Plugin\migrate\process\d6\InternalUri | transform | Not OK (converts the tel:xxx URL to internal:/tel:xxx) |
\Drupal\shortcut\Controller \ShortcutSetController | addShortcutLinkInline | Not OK (converts the tel:xxx URL to internal:/tel:xxx but it's not likely to happens in shortcuts) |
core/modules/system/system.module | system_retrieve_file | Can throw notices but not likely to be used with a tel URI |
Proposed resolution
We have Drupal\Component\Utility\UrlHelper (URL). We should create a similar UrIHelper (URI) class which is a true RFC 3986 parser.
Note: An external parser can't be used with our current Drupal requirements (PHP 5.6+ or php-intl requirements, both which Drupal doesn't have now)
Wrap parse_url
in a drupal_parse_uri
function so we can manage all specific cases and unit test it.
Remaining tasks
Discuss, Fix PHP, Fix Drupal, Enjoy
User interface changes
None.
API changes
An added URIHelper class.
Data model changes
None.