From ed4969a4f8ae6c2df0c64bca684a22ed5aa525df Mon Sep 17 00:00:00 2001 From: MuK IT GmbH Date: Mon, 27 Jul 2020 21:45:52 +0000 Subject: [PATCH] publish muk_utils - 13.0 --- muk_utils/__manifest__.py | 2 +- muk_utils/models/__init__.py | 1 + muk_utils/models/scss_editor.py | 146 ++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 muk_utils/models/scss_editor.py diff --git a/muk_utils/__manifest__.py b/muk_utils/__manifest__.py index a541d50..2afb252 100644 --- a/muk_utils/__manifest__.py +++ b/muk_utils/__manifest__.py @@ -40,4 +40,4 @@ "application": False, "installable": True, "auto_install": False, -} +} \ No newline at end of file diff --git a/muk_utils/models/__init__.py b/muk_utils/models/__init__.py index e6b2d51..9342c14 100644 --- a/muk_utils/models/__init__.py +++ b/muk_utils/models/__init__.py @@ -27,4 +27,5 @@ from . import ( mixins_groups, mixins_hierarchy, res_config_settings, + scss_editor, ) diff --git a/muk_utils/models/scss_editor.py b/muk_utils/models/scss_editor.py new file mode 100644 index 0000000..8034b0a --- /dev/null +++ b/muk_utils/models/scss_editor.py @@ -0,0 +1,146 @@ +################################################################################### +# +# Copyright (c) 2017-2019 MuK IT GmbH. +# +# This file is part of MuK Utils +# (see https://mukit.at). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +################################################################################### + +import re +import uuid +import base64 + +from odoo import models, fields, api +from odoo.modules import module + + +class ScssEditor(models.AbstractModel): + _name = 'muk_utils.scss_editor' + _description = 'Scss Editor' + + # ---------------------------------------------------------- + # Helper + # ---------------------------------------------------------- + + def _build_custom_url(self, url_parts, xmlid): + return "%s.custom.%s.%s" % (url_parts[0], xmlid, url_parts[1]) + + def _get_custom_url(self, url, xmlid): + return self._build_custom_url(url.rsplit(".", 1), xmlid) + + def _get_custom_attachment(self, url): + return self.env["ir.attachment"].with_context( + bin_size=False, bin_size_datas=False + ).search([("url", '=', url)], limit=1) + + def _get_custom_view(self, url): + return self.env["ir.ui.view"].search([("name", '=', url)]) + + def _get_variable(self, content, variable): + regex = r'{0}\:?\s(.*?);'.format(variable) + value = re.search(regex, content) + return value and value.group(1) + + def _get_variables(self, content, variables): + return {var: self._get_variable(content, var) for var in variables} + + def _replace_variables(self, content, variables): + for variable in variables: + variable_content = '{0}: {1};'.format( + variable['name'], + variable['value'] + ) + regex = r'{0}\:?\s(.*?);'.format(variable['name']) + content = re.sub(regex, variable_content, content) + return content + + # ---------------------------------------------------------- + # Read + # ---------------------------------------------------------- + + def get_content(self, url, xmlid): + custom_url = self._get_custom_url(url, xmlid) + custom_attachment = self._get_custom_attachment(custom_url) + if custom_attachment.exists(): + return base64.b64decode(custom_attachment.datas).decode('utf-8') + else: + match = re.compile("^/(\w+)/(.+?)(\.custom\.(.+))?\.(\w+)$").match(url) + module_path = module.get_module_path(match.group(1)) + resource_path = "%s.%s" % (match.group(2), match.group(5)) + module_resource_path = module.get_resource_path(module_path, resource_path) + with open(module_resource_path, "rb") as file: + return file.read().decode('utf-8') + + def get_values(self, url, xmlid, variables): + return self._get_variables(self.get_content(url, xmlid), variables) + + # ---------------------------------------------------------- + # Write + # ---------------------------------------------------------- + + def replace_content(self, url, xmlid, content): + custom_url = self._get_custom_url(url, xmlid) + custom_view = self._get_custom_view(custom_url) + custom_attachment = self._get_custom_attachment(custom_url) + datas = base64.b64encode((content or "\n").encode("utf-8")) + if custom_attachment.exists(): + custom_attachment.write({"datas": datas}) + else: + self.env["ir.attachment"].create({ + 'name': custom_url, + 'type': "binary", + 'mimetype': "text/scss", + 'datas': datas, + # TODO: old field datas_fname got removed, check if store_fname is correct and write migration + 'store_fname': url.split("/")[-1], + 'url': custom_url, + }) + if not custom_view.exists(): + view_to_xpath = self.env["ir.ui.view"].get_related_views( + xmlid, bundles=True + ).filtered(lambda v: v.arch.find(url) >= 0) + self.env["ir.ui.view"].create({ + 'name': custom_url, + 'key': 'web_editor.scss_%s' % str(uuid.uuid4())[:6], + 'mode': "extension", + 'priority': view_to_xpath.priority, + 'inherit_id': view_to_xpath.id, + 'arch': """ + + + %(new_url)s + + + """ % { + 'inherit_xml_id': view_to_xpath.xml_id, + 'name': custom_url, + 'url_to_replace': url, + 'new_url': custom_url, + } + }) + self.env["ir.qweb"].clear_caches() + + def replace_values(self, url, xmlid, variables): + content = self._replace_variables( + self.get_content(url, xmlid), variables + ) + self.replace_content(url, xmlid, content) + + def reset_values(self, url, xmlid): + custom_url = self._get_custom_url(url, xmlid) + self._get_custom_attachment(custom_url).unlink() + self._get_custom_view(custom_url).unlink()