[FIX] ir_qweb: don't use a stylesheet cached by another bundle.

An issue could arise if a preprocessed stylesheet asset is present
in multiple bundles: the first bundle will cache a version of this
file (identified by its url) and the second one will cache another
one. The next time the first bundle is rendered in debug mode, it
will use the last created record of the asset.

This could lead to design issues as, for instance, a less asset
could change according to another less asset included in the bundle.

We fix this issue by adding the xmlid of the bundle in the url's
asset. This fix another inconsistency as the compiled version of
an asset is reachable with an url that is not dependent of its
bundle, so if the asset is present in multiple bundle it could
return different values.

Note: this only concern the debug mode
This commit is contained in:
Simon Lejeune
2016-03-03 17:38:20 +01:00
parent 0806506c9c
commit 9631a30228
+15 -6
View File
@@ -1340,7 +1340,7 @@ class AssetsBundle(object):
preprocessed = True
for atype in (SassStylesheetAsset, LessStylesheetAsset):
outdated = False
assets = dict((asset.html_url % asset.url, asset) for asset in self.stylesheets if isinstance(asset, atype))
assets = dict((asset.html_url, asset) for asset in self.stylesheets if isinstance(asset, atype))
if assets:
assets_domain = [('url', 'in', assets.keys())]
ira_ids = self.registry['ir.attachment'].search(self.cr, uid, assets_domain)
@@ -1391,7 +1391,7 @@ class AssetsBundle(object):
try:
ira = self.registry['ir.attachment']
fname = os.path.basename(asset.url)
url = asset.html_url % asset.url
url = asset.html_url
with self.cr.savepoint():
ira.create(self.cr, openerp.SUPERUSER_ID, dict(
datas=asset.content.encode('utf8').encode('base64'),
@@ -1455,13 +1455,14 @@ class AssetsBundle(object):
return error
class WebAsset(object):
html_url = '%s'
html_url_format = '%s'
def __init__(self, bundle, inline=None, url=None):
self.id = str(uuid.uuid4())
self.bundle = bundle
self.inline = inline
self.url = url
self.html_url_args = url
self.cr = bundle.cr
self.uid = bundle.uid
self.registry = bundle.registry
@@ -1474,6 +1475,10 @@ class WebAsset(object):
if not inline and not url:
raise Exception("An asset should either be inlined or url linked")
@property
def html_url(self):
return self.html_url_format % self.html_url_args
def stat(self):
if not (self.inline or self._filename or self._ir_attach):
path = filter(None, self.url.split('/'))
@@ -1552,7 +1557,7 @@ class JavascriptAsset(WebAsset):
def to_html(self):
if self.url:
return '<script type="text/javascript" src="%s"></script>' % (self.html_url % self.url)
return '<script type="text/javascript" src="%s"></script>' % (self.html_url)
else:
return '<script type="text/javascript" charset="utf-8">%s</script>' % self.with_header()
@@ -1612,15 +1617,19 @@ class StylesheetAsset(WebAsset):
def to_html(self):
media = (' media="%s"' % werkzeug.utils.escape(self.media)) if self.media else ''
if self.url:
href = self.html_url % self.url
href = self.html_url
return '<link rel="stylesheet" href="%s" type="text/css"%s/>' % (href, media)
else:
return '<style type="text/css"%s>%s</style>' % (media, self.with_header())
class PreprocessedCSS(StylesheetAsset):
html_url = '%s.css'
rx_import = None
def __init__(self, *args, **kw):
super(PreprocessedCSS, self).__init__(*args, **kw)
self.html_url_format = '%%s/%s/%%s.css' % self.bundle.xmlid
self.html_url_args = tuple(self.url.rsplit('/', 1))
def minify(self):
return self.with_header()