summaryrefslogtreecommitdiff
path: root/addons/web_editor/models
diff options
context:
space:
mode:
authorfja-odoo <fja@odoo.com>2020-05-13 08:52:12 +0000
committerfja-odoo <fja@odoo.com>2020-05-20 13:20:35 +0000
commit049745c5fffcd11894cd5f9b38078c993d2ef969 (patch)
tree0c52321af364561becd5fe193ddcc4ad9f71cb81 /addons/web_editor/models
parente3b4f3ddf43f309eea7272fe78dcbb2eb4e90a6c (diff)
[FIX] web_editor: fix _view_get infinite recursion
The _view_get function is a recursive function used to retieve all the views related to a view (inherited or t-called). The issue is that by an odd set of circumstances it is possible to have a loop in the view graph. Resulting in the recursive function being called until a "maximum recursion depth exceeded" error occurs. Example of a loop: A t-call B and A inherit from B This is possible on an update of a view that has been forked by website: If the view A was doing a t-call on B and is has been duplicated with the arch modified. When we update with the changes A now inherit from B instead of t-call B Since the arch was modified it will not be updated so A will still t-call B but the inherit_id of A is unchanged so it will be updated to reference B resulting in a loop. closes odoo/odoo#51620 X-original-commit: 63e1e84ebd7e609d6e06d83dc0f0092688b013eb Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Diffstat (limited to 'addons/web_editor/models')
-rw-r--r--addons/web_editor/models/ir_ui_view.py15
1 files changed, 9 insertions, 6 deletions
diff --git a/addons/web_editor/models/ir_ui_view.py b/addons/web_editor/models/ir_ui_view.py
index c56fdadbb6e..a3bfd773a92 100644
--- a/addons/web_editor/models/ir_ui_view.py
+++ b/addons/web_editor/models/ir_ui_view.py
@@ -224,7 +224,7 @@ class IrUiView(models.Model):
# Used by translation mechanism, SEO and optional templates
@api.model
- def _views_get(self, view_id, get_children=True, bundles=False, root=True):
+ def _views_get(self, view_id, get_children=True, bundles=False, root=True, visited=None):
""" For a given view ``view_id``, should return:
* the view itself
* all views inheriting from it, enabled or not
@@ -238,6 +238,8 @@ class IrUiView(models.Model):
_logger.warning("Could not find view object with view_id '%s'", view_id)
return self.env['ir.ui.view']
+ if visited is None:
+ visited = []
while root and view.inherit_id:
view = view.inherit_id
@@ -252,8 +254,8 @@ class IrUiView(models.Model):
called_view = self._view_obj(child.get('t-call', child.get('t-call-assets')))
except ValueError:
continue
- if called_view and called_view not in views_to_return:
- views_to_return += self._views_get(called_view, get_children=get_children, bundles=bundles)
+ if called_view and called_view not in views_to_return and called_view.id not in visited:
+ views_to_return += self._views_get(called_view, get_children=get_children, bundles=bundles, visited=visited + views_to_return.ids)
if not get_children:
return views_to_return
@@ -263,9 +265,10 @@ class IrUiView(models.Model):
# Keep children in a deterministic order regardless of their applicability
for extension in extensions.sorted(key=lambda v: v.id):
# only return optional grandchildren if this child is enabled
- for ext_view in self._views_get(extension, get_children=extension.active, root=False):
- if ext_view not in views_to_return:
- views_to_return += ext_view
+ if extension.id not in visited:
+ for ext_view in self._views_get(extension, get_children=extension.active, root=False, visited=visited + views_to_return.ids):
+ if ext_view not in views_to_return:
+ views_to_return += ext_view
return views_to_return
@api.model