diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index a94ef8b9b76..424ba3b8910 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1002,6 +1002,7 @@ class Binary(http.Controller): '/web/content//', '/web/content/-', '/web/content/-/', + '/web/content/-//', '/web/content///', '/web/content////'], type='http', auth="public") def content_common(self, xmlid=None, model='ir.attachment', id=None, field='datas', diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index 0f73bc469f5..090502aa56f 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -5,11 +5,22 @@ from collections import OrderedDict from odoo import models from odoo.http import request +from odoo.addons.base.models.assetsbundle import AssetsBundle + re_background_image = re.compile(r"(background-image\s*:\s*url\(\s*['\"]?\s*)([^)'\"]+)") +class AssetsBundleMultiWebsite(AssetsBundle): + def _get_asset_url_values(self, id, unique, extra, name, page, type): + website_id = self.env.context.get('website_id') + website_id_path = website_id and ('%s/' % website_id) or '' + extra = website_id_path + extra + res = super(AssetsBundleMultiWebsite, self)._get_asset_url_values(id, unique, extra, name, page, type) + return res + + class QWeb(models.AbstractModel): """ QWeb object for rendering stuff in the website context """ @@ -23,6 +34,9 @@ class QWeb(models.AbstractModel): 'img': 'src', } + def get_asset_bundle(self, xmlid, files, remains=None, env=None): + return AssetsBundleMultiWebsite(xmlid, files, remains=remains, env=env) + def _post_processing_att(self, tagName, atts, options): if atts.get('data-no-post-process'): return atts diff --git a/odoo/addons/base/models/assetsbundle.py b/odoo/addons/base/models/assetsbundle.py index a2d56e4fa02..121ba2fd968 100644 --- a/odoo/addons/base/models/assetsbundle.py +++ b/odoo/addons/base/models/assetsbundle.py @@ -198,6 +198,24 @@ class AssetsBundle(object): check = u"%s%s" % (json.dumps(self.files, sort_keys=True), self.last_modified) return hashlib.sha1(check.encode('utf-8')).hexdigest() + def _get_asset_template_url(self): + return "/web/content/{id}-{unique}/{extra}{name}{page}{type}" # name contains inc + + def _get_asset_url_values(self, id, unique, extra, name, page, type): # extra can contain direction or/and website + return { + 'id': id, + 'unique': unique, + 'extra': extra, + 'name': name, + 'page': page, + 'type': type, + } + + def get_asset_url(self, id='%', unique='%', extra='', name='%', page='%', type='%'): + return self._get_asset_template_url().format( + **self._get_asset_url_values(id=id, unique=unique, extra=extra, name=name, page=page, type=type) + ) + def clean_attachments(self, type): """ Takes care of deleting any outdated ir.attachment records associated to a bundle before saving a fresh one. @@ -213,13 +231,14 @@ class AssetsBundle(object): must exclude the current bundle. """ ira = self.env['ir.attachment'] + url = self.get_asset_url( + extra='%s' % ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''), + name=self.name, + type=type + ) domain = [ - ('url', '=like', '/web/content/%-%-{}/{}{}%.{}'.format( # The wilcards are id, version and pagination number (if any) - self.env.context.get('website_id'), - ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''), - self.name, - type)), - '!', ('url', '=like', '/web/content/%-{}/%'.format(self.version)) + ('url', '=like', url), + '!', ('url', '=like', self.get_asset_url(unique=self.version)) ] # force bundle invalidation on other workers @@ -235,14 +254,13 @@ class AssetsBundle(object): multiple time the same bundle in our `to_html` function, we group our ir.attachment records by file name and only return the one with the max id for each group. """ - version = "%" if ignore_version else self.version - url_pattern = '/web/content/%-{}-{}/{}{}{}.{}'.format( - version, - self.env.context.get('website_id'), - ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''), - self.name, - '.%' if type == 'css' else '', - type + unique = "%" if ignore_version else self.version + url_pattern = self.get_asset_url( + unique=unique, + extra='%s' % ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''), + name=self.name, + page='.%' if type == 'css' else '', + type='.%s' % type ) self.env.cr.execute(""" SELECT max(id) @@ -281,12 +299,13 @@ class AssetsBundle(object): } attachment = ira.sudo().create(values) - url = '/web/content/%s-%s-%s%s/%s' % ( - attachment.id, - self.version, - self.env.context.get('website_id'), - ('/rtl' if type == 'css' and self.user_direction == 'rtl' else ''), - fname + url = self.get_asset_url( + id=attachment.id, + unique=self.version, + extra='%s' % ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''), + name=fname, + page='', # included in fname + type='' # included in fname ) values = { 'name': url,