Repository: ckan/ckan

Issue:
plugin template order reversed (since #7033)
**CKAN version**
master

**Describe the bug**
After we swapped the order of calling plugins' update_config hooks the resulting order of templates and public directories is now reversed

**Steps to reproduce**
have more than one plugin that adds template directories

**Expected behavior**
first plugin templates override later plugin templates (historic behaviour)

**Additional details**




Discussion:

Resolving patch:
diff --git a/ckan/config/environment.py b/ckan/config/environment.py
--- a/ckan/config/environment.py
+++ b/ckan/config/environment.py
@@ -191,6 +191,8 @@ def update_config() -> None:
     template_paths = [jinja2_templates_path]
 
     extra_template_paths = config.get_value('extra_template_paths')
+    if 'plugin_template_paths' in config:
+        template_paths = config['plugin_template_paths'] + template_paths
     if extra_template_paths:
         # must be first for them to override defaults
         template_paths = extra_template_paths.split(',') + template_paths
diff --git a/ckan/config/middleware/flask_app.py b/ckan/config/middleware/flask_app.py
--- a/ckan/config/middleware/flask_app.py
+++ b/ckan/config/middleware/flask_app.py
@@ -145,7 +145,9 @@ def make_flask_stack(conf: Union[Config, CKANConfig]) -> CKANApp:
     public_folder = config.get_value(u'ckan.base_public_folder')
     app.static_folder = config.get_value(
         'extra_public_paths'
-    ).split(',') + [os.path.join(root, public_folder)] + storage_folder
+    ).split(',') + config.get('plugin_public_paths', []) + [
+        os.path.join(root, public_folder)
+    ] + storage_folder
 
     app.jinja_options = jinja_extensions.get_jinja_env_options()
     app.jinja_env.policies['ext.i18n.trimmed'] = True
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -123,7 +123,7 @@ def add_template_directory(config_: CKANConfig, relative_path: str):
     The path is relative to the file calling this function.
 
     """
-    _add_served_directory(config_, relative_path, "extra_template_paths")
+    _add_served_directory(config_, relative_path, "plugin_template_paths")
 
 
 def add_public_directory(config_: CKANConfig, relative_path: str):
@@ -139,7 +139,7 @@ def add_public_directory(config_: CKANConfig, relative_path: str):
     from ckan.lib.helpers import _local_url
     from ckan.lib.webassets_tools import add_public_path
 
-    path = _add_served_directory(config_, relative_path, "extra_public_paths")
+    path = _add_served_directory(config_, relative_path, "plugin_public_paths")
     url = _local_url("/", locale="default")
     add_public_path(path, url)
 
@@ -150,18 +150,18 @@ def _add_served_directory(
     import inspect
     import os
 
-    assert config_var in ("extra_template_paths", "extra_public_paths")
+    assert config_var in ("plugin_template_paths", "plugin_public_paths")
     # we want the filename that of the function caller but they will
     # have used one of the available helper functions
     filename = inspect.stack()[2].filename
 
     this_dir = os.path.dirname(filename)
     absolute_path = os.path.join(this_dir, relative_path)
-    if absolute_path not in config_.get_value(config_var).split(","):
-        if config_.get_value(config_var):
-            config_[config_var] += "," + absolute_path
+    if absolute_path not in config_.get(config_var, []):
+        if config_var in config_:
+            config_[config_var] = [absolute_path] + config_[config_var]
         else:
-            config_[config_var] = absolute_path
+            config_[config_var] = [absolute_path]
     return absolute_path
 
 


Test patch:
diff --git a/ckan/tests/helpers.py b/ckan/tests/helpers.py
--- a/ckan/tests/helpers.py
+++ b/ckan/tests/helpers.py
@@ -598,6 +598,7 @@ class FakeSMTP(smtplib.SMTP):
 
     def __init__(self):
         self._msgs = []
+        self.esmtp_features = ['starttls']
 
     def __call__(self, *args):
         return self