diff --git a/wagtail/core/rich_text/__init__.py b/wagtail/core/rich_text/__init__.py index 2066ff2d0..f44971b7d 100644 --- a/wagtail/core/rich_text/__init__.py +++ b/wagtail/core/rich_text/__init__.py @@ -67,7 +67,10 @@ class EntityHandler: """ @staticmethod def get_model(): - return NotImplementedError + """ + If supported, returns the type of model able to be handled by this handler, e.g. Page. + """ + raise NotImplementedError @classmethod def get_instance(cls, attrs: dict) -> Model: diff --git a/wagtail/core/rich_text/feature_registry.py b/wagtail/core/rich_text/feature_registry.py index 9bef84be0..2319ceff8 100644 --- a/wagtail/core/rich_text/feature_registry.py +++ b/wagtail/core/rich_text/feature_registry.py @@ -1,4 +1,7 @@ +from warnings import warn + from wagtail.core import hooks +from wagtail.utils.deprecation import RemovedInWagtail27Warning class FeatureRegistry: @@ -68,16 +71,40 @@ class FeatureRegistry: except KeyError: return None - def register_link_type(self, handler): - self.link_types[handler.identifier] = handler + def register_link_type(self, identifier_or_handler_obj, handler_fn=None): + if handler_fn is not None: + # invoked as register_link_type(identifier, handler_function) - deprecated + identifier = identifier_or_handler_obj + warn( + 'FeatureRegistry.register_link_type(link_type, handler_function) is deprecated. ' + 'Use FeatureRegistry.register_link_type(handler_object) instead', + category=RemovedInWagtail27Warning + ) + self.link_types[identifier] = self.function_as_entity_handler(identifier, handler_fn) + else: + # invoked as register_link_type(handler_object) + handler = identifier_or_handler_obj + self.link_types[handler.identifier] = handler def get_link_types(self): if not self.has_scanned_for_features: self._scan_for_features() return self.link_types - def register_embed_type(self, handler): - self.embed_types[handler.identifier] = handler + def register_embed_type(self, identifier_or_handler_obj, handler_fn=None): + if handler_fn is not None: + # invoked as register_embed_type(identifier, handler_function) - deprecated + identifier = identifier_or_handler_obj + warn( + 'FeatureRegistry.register_embed_type(link_type, handler_function) is deprecated. ' + 'Use FeatureRegistry.register_embed_type(handler_object) instead', + category=RemovedInWagtail27Warning + ) + self.embed_types[identifier] = self.function_as_entity_handler(identifier, handler_fn) + else: + # invoked as register_embed_type(handler_object) + handler = identifier_or_handler_obj + self.embed_types[handler.identifier] = handler def get_embed_types(self): if not self.has_scanned_for_features: @@ -96,3 +123,11 @@ class FeatureRegistry: return self.converter_rules_by_converter[converter_name][feature_name] except KeyError: return None + + @staticmethod + def function_as_entity_handler(identifier, fn): + """Supports legacy registering of entity handlers as functions.""" + return type('EntityHandlerRegisteredAsFunction', (object,), { + 'identifier': identifier, + 'expand_db_attributes': staticmethod(fn), + }) diff --git a/wagtail/core/tests/test_rich_text.py b/wagtail/core/tests/test_rich_text.py index 95b1547d8..2d62e2677 100644 --- a/wagtail/core/tests/test_rich_text.py +++ b/wagtail/core/tests/test_rich_text.py @@ -1,5 +1,6 @@ from unittest.mock import patch +from django.contrib.auth import get_user_model from django.test import TestCase from wagtail.core.rich_text import RichText, expand_db_html @@ -95,6 +96,36 @@ class TestFeatureRegistry(TestCase): features.get_editor_plugin('hallo', 'made_up_feature') ) + def test_legacy_register_link_type(self): + User = get_user_model() + User.objects.create(username='wagtail', email='hello@wagtail.io') + + def user_expand_db_attributes(attrs): + user = User.objects.get(username=attrs['username']) + return '' % user.email + + features = FeatureRegistry() + features.register_link_type('user', user_expand_db_attributes) + + handler = features.get_link_types()['user'] + self.assertEqual( + handler.expand_db_attributes({'username': 'wagtail'}), + '' + ) + + def test_legacy_register_embed_type(self): + def embed_expand_db_attributes(attrs): + return '
embedded content: %s
' % attrs['content'] + + features = FeatureRegistry() + features.register_embed_type('mock_embed', embed_expand_db_attributes) + + handler = features.get_embed_types()['mock_embed'] + self.assertEqual( + handler.expand_db_attributes({'content': 'foo'}), + '
embedded content: foo
' + ) + class TestLinkRewriterTagReplacing(TestCase): def test_should_follow_default_behaviour(self):