diff --git a/wagtail/admin/views/workflows.py b/wagtail/admin/views/workflows.py index af9b03f47f..1227afa235 100644 --- a/wagtail/admin/views/workflows.py +++ b/wagtail/admin/views/workflows.py @@ -17,6 +17,7 @@ from wagtail.admin.views.generic import CreateView, DeleteView, EditView, IndexV from wagtail.admin.views.pages import get_valid_next_url_from_request from wagtail.core.models import Page, Task, TaskState, WorkflowState from wagtail.core.permissions import task_permission_policy, workflow_permission_policy +from wagtail.core.workflows import get_task_types class Index(IndexView): @@ -290,7 +291,7 @@ def select_task_type(request): task_types = [ (model.get_verbose_name(), model._meta.app_label, model._meta.model_name) - for model in Task.__subclasses__() + for model in get_task_types() ] # sort by lower-cased version of verbose name task_types.sort(key=lambda task_type: task_type[0].lower()) diff --git a/wagtail/core/workflows.py b/wagtail/core/workflows.py index 05d77b8b44..a6967d233d 100644 --- a/wagtail/core/workflows.py +++ b/wagtail/core/workflows.py @@ -1,3 +1,27 @@ +from wagtail.core.models import Task + + +TASK_TYPES = [] + +def get_concrete_descendants(model_class, inclusive=True): + """Retrieves non-abstract descendants of the given model class. If `inclusive` is set to + True, includes model_class""" + subclasses = model_class.__subclasses__() + if subclasses: + for subclass in subclasses: + yield from get_concrete_descendants(subclass) + if inclusive and not model_class._meta.abstract: + yield model_class + + +def get_task_types(task_class=None): + global TASK_TYPES + if TASK_TYPES: + return TASK_TYPES + TASK_TYPES = list(get_concrete_descendants(Task, inclusive=False)) + return TASK_TYPES + + def publish_workflow_state(workflow_state): # publish the Page associated with a WorkflowState if workflow_state.current_task_state: