Add link conversion configuration setting

pull/7427/head
jacobtoppm 2021-08-03 16:24:43 +01:00 zatwierdzone przez Jacob Topp-Mugglestone
rodzic b7a37330bd
commit 7bf3f813ef
3 zmienionych plików z 79 dodań i 4 usunięć

Wyświetl plik

@ -826,6 +826,19 @@ Customise the behaviour of rich text fields. By default, ``RichTextField`` and `
If a ``'default'`` editor is not specified, rich text fields that do not specify an ``editor`` argument will use the Draftail editor with the default feature set enabled.
``WAGTAILADMIN_EXTERNAL_LINK_CONVERSION``
-----------------------------------------
.. code-block:: python
WAGTAILADMIN_EXTERNAL_LINK_CONVERSION = 'exact'
Customise Wagtail's behaviour when an internal page url is entered in the external link chooser. Possible values for this setting are
``'all'``, ``'exact'``, ``'confirm``, or ``''``. The default, ``'all'``, means that Wagtail will automatically convert submitted urls that exactly match
page urls to the corresponding internal links. If the url is an inexact match - for example, the submitted url has query parameters - then
Wagtail will confirm the conversion with the user. ``'exact'`` means that any inexact matches will be left as external urls, and the confirmation
step will be skipped. ``'confirm'`` means that every link conversion will be confirmed with the user, even if the match is exact. ``''`` means
that Wagtail will not attempt to convert any urls entered to internal page links.
.. _WAGTAILADMIN_GLOBAL_PAGE_EDIT_LOCK:

Wyświetl plik

@ -1,7 +1,7 @@
import json
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils.http import urlencode
@ -603,6 +603,45 @@ class TestChooserExternalLink(TestCase, WagtailTestUtils):
self.assertEqual(response_json['result']['url'], "/about/")
self.assertEqual(response_json['result']['id'], self.internal_page.pk)
@override_settings(WAGTAILADMIN_EXTERNAL_LINK_CONVERSION='')
def test_no_conversion_external_to_internal_link_when_disabled(self):
url = 'http://localhost/about/'
title = 'about'
response = self.post({'external-link-chooser-url': url, 'external-link-chooser-link_text': title})
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content.decode())
self.assertEqual(response_json['step'], 'external_link_chosen')
self.assertEqual(response_json['result']['url'], url)
self.assertEqual(response_json['result']['title'], title)
@override_settings(WAGTAILADMIN_EXTERNAL_LINK_CONVERSION='exact')
def test_no_confirm_external_to_internal_link_when_exact(self):
url = 'http://localhost/about?test=1'
title = 'about'
response = self.post({'external-link-chooser-url': url, 'external-link-chooser-link_text': title})
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content.decode())
# Query parameters will get stripped, so this link should be left as an external url with the 'exact' setting
self.assertEqual(response_json['step'], 'external_link_chosen')
self.assertEqual(response_json['result']['url'], url)
self.assertEqual(response_json['result']['title'], title)
@override_settings(WAGTAILADMIN_EXTERNAL_LINK_CONVERSION='confirm')
def test_convert_external_link_to_internal_link_with_confirm_setting(self):
url = 'http://localhost/about/'
response = self.post({'external-link-chooser-url': url, 'external-link-chooser-link_text': 'about'})
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content.decode())
# The url is identical, but the conversion setting is set to 'confirm'
# so the user should get asked to confirm the conversion
self.assertEqual(response_json['step'], 'confirm_external_to_internal')
self.assertEqual(response_json['external']['url'], url)
self.assertEqual(response_json['internal']['id'], self.internal_page.pk)
class TestChooserAnchorLink(TestCase, WagtailTestUtils):
def setUp(self):

Wyświetl plik

@ -1,5 +1,6 @@
import re
from django.conf import settings
from django.core.paginator import Paginator
from django.http import Http404
from django.shortcuts import get_object_or_404
@ -183,6 +184,11 @@ def search(request, parent_page_id=None):
)
LINK_CONVERSION_ALL = 'all'
LINK_CONVERSION_EXACT = 'exact'
LINK_CONVERSION_CONFIRM = 'confirm'
def external_link(request):
initial_data = {
'url': request.GET.get('link_url', ''),
@ -205,12 +211,23 @@ def external_link(request):
'prefer_this_title_as_link_text': ('link_text' in form.changed_data),
}
link_conversion = getattr(settings, 'WAGTAILADMIN_EXTERNAL_LINK_CONVERSION', LINK_CONVERSION_ALL).lower()
if link_conversion not in [LINK_CONVERSION_ALL, LINK_CONVERSION_EXACT, LINK_CONVERSION_CONFIRM]:
# We should not attempt to convert external urls to page links
return render_modal_workflow(
request, None, None,
None, json_data={'step': 'external_link_chosen', 'result': result}
)
# Next, we should check if the url matches an internal page
# Strip the url of its query/fragment link parameters - these won't match a page
url_without_query = re.split(r"\?|#", submitted_url)[0]
# Start by finding any sites the url could potentially match
sites = getattr(request, '_wagtail_cached_site_root_paths', Site.get_site_root_paths())
sites = getattr(request, '_wagtail_cached_site_root_paths', None)
if sites is None:
sites = Site.get_site_root_paths()
match_relative_paths = submitted_url.startswith('/') and len(sites) == 1
# We should only match relative urls if there's only a single site
@ -253,8 +270,9 @@ def external_link(request):
normal_url = matched_page.get_url_parts(request=request)[-1] if match_relative_paths else matched_page.get_full_url(request=request)
# If that's what the user provided, great. Let's just convert the external
# url to an internal link automatically
if normal_url == submitted_url:
# url to an internal link automatically unless we're set up tp manually check
# all conversions
if normal_url == submitted_url and link_conversion != LINK_CONVERSION_CONFIRM:
return render_modal_workflow(
request,
None,
@ -263,6 +281,11 @@ def external_link(request):
json_data={'step': 'external_link_chosen', 'result': internal_data}
)
# If not, they might lose query parameters or routable page information
if link_conversion == LINK_CONVERSION_EXACT:
# We should only convert exact matches
continue
# Let's confirm the conversion with them explicitly
else:
return render_modal_workflow(