From 37fcb1e6ff371ffbeb81a3825c24a4ed0afbf75f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 19 Oct 2018 11:57:17 +0000 Subject: [PATCH] [REF] link_tracker: reorganize python according to guidelines This was not correctly done when splitting the module at fd5361c0f7116e951cf9e69e2d97a8ccb07ce1b6. Future commits will clean a bit the code in order to better understand how this module works. This commit is linked to task ID 1896681 and PR #27975. No functional change should occur with this commit as it contains only renaming / move. --- addons/link_tracker/models/link_tracker.py | 158 +++++++++++---------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/addons/link_tracker/models/link_tracker.py b/addons/link_tracker/models/link_tracker.py index f5db16a35fc..81c2a03e465 100644 --- a/addons/link_tracker/models/link_tracker.py +++ b/addons/link_tracker/models/link_tracker.py @@ -17,6 +17,7 @@ from odoo.tools import ustr URL_REGEX = r'(\bhref=[\'"](?!mailto:|tel:|sms:)([^\'"]+)[\'"])' + def VALIDATE_URL(url): if urls.url_parse(url).scheme not in ('http', 'https', 'ftp', 'ftps'): return 'http://' + url @@ -24,50 +25,32 @@ def VALIDATE_URL(url): return url -class link_tracker(models.Model): - """link_tracker allow users to wrap any URL into a short and trackable URL. - link_tracker counts clicks on each tracked link. - This module is also used by mass_mailing, where each link in mail_mail html_body are converted into - a trackable link to get the click-through rate of each mass_mailing.""" +class LinkTracker(models.Model): + """ Link trackers allow users to wrap any URL into a short URL that can be + tracked by Odoo. Clicks are counter on each link. A tracker is linked to + UTMs allowing to analyze marketing actions. + This model is also used in mass_mailing where each link in html body is + automatically converted into a short link that is tracked and integrates + UTMs. """ _name = "link.tracker" _rec_name = "short_url" - _description = 'Link Tracker' - - _inherit = ['utm.mixin'] + _description = "Link Tracker" + _inherit = ["utm.mixin"] + # URL info url = fields.Char(string='Target URL', required=True) - count = fields.Integer(string='Number of Clicks', compute='_compute_count', store=True) short_url = fields.Char(string='Tracked URL', compute='_compute_short_url') - link_click_ids = fields.One2many('link.tracker.click', 'link_id', string='Clicks') - title = fields.Char(string='Page Title', store=True) - favicon = fields.Char(string='Favicon', compute='_compute_favicon', store=True) - link_code_ids = fields.One2many('link.tracker.code', 'link_id', string='Codes') - code = fields.Char(string='Short URL code', compute='_compute_code') redirected_url = fields.Char(string='Redirected URL', compute='_compute_redirected_url') short_url_host = fields.Char(string='Host of the short URL', compute='_compute_short_url_host') + title = fields.Char(string='Page Title', store=True) + favicon = fields.Char(string='Favicon', compute='_compute_favicon', store=True) icon_src = fields.Char(string='Favicon Source', compute='_compute_icon_src') - - @api.model - def convert_links(self, html, vals, blacklist=None): - for match in re.findall(URL_REGEX, html): - - short_schema = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + '/r/' - - href = match[0] - long_url = match[1] - - vals['url'] = utils.unescape(long_url) - - if not blacklist or not [s for s in blacklist if s in long_url] and not long_url.startswith(short_schema): - link = self.create(vals) - shorten_url = self.browse(link.id)[0].short_url - - if shorten_url: - new_href = href.replace(long_url, shorten_url) - html = html.replace(href, new_href) - - return html + # Tracking + link_code_ids = fields.One2many('link.tracker.code', 'link_id', string='Codes') + code = fields.Char(string='Short URL code', compute='_compute_code') + link_click_ids = fields.One2many('link.tracker.click', 'link_id', string='Clicks') + count = fields.Integer(string='Number of Clicks', compute='_compute_count', store=True) @api.one @api.depends('link_click_ids.link_id') @@ -131,6 +114,60 @@ class link_tracker(models.Model): self.favicon = icon_base64 + @api.model + def create(self, vals): + create_vals = vals.copy() + + if 'url' not in create_vals: + raise ValueError('URL field required') + else: + create_vals['url'] = VALIDATE_URL(vals['url']) + + search_domain = [] + for fname, value in create_vals.items(): + search_domain.append((fname, '=', value)) + + result = self.search(search_domain, limit=1) + + if result: + return result + + if not create_vals.get('title'): + create_vals['title'] = self._get_title_from_url(create_vals['url']) + + # Prevent the UTMs to be set by the values of UTM cookies + for (key, fname, cook) in self.env['utm.mixin'].tracking_fields(): + if fname not in create_vals: + create_vals[fname] = False + + link = super(LinkTracker, self).create(create_vals) + + code = self.env['link.tracker.code'].get_random_code_string() + self.env['link.tracker.code'].sudo().create({'code': code, 'link_id': link.id}) + + return link + + @api.model + def convert_links(self, html, vals, blacklist=None): + for match in re.findall(URL_REGEX, html): + + short_schema = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + '/r/' + + href = match[0] + long_url = match[1] + + vals['url'] = utils.unescape(long_url) + + if not blacklist or not [s for s in blacklist if s in long_url] and not long_url.startswith(short_schema): + link = self.create(vals) + shorten_url = self.browse(link.id)[0].short_url + + if shorten_url: + new_href = href.replace(long_url, shorten_url) + html = html.replace(href, new_href) + + return html + @api.multi def action_view_statistics(self): action = self.env['ir.actions.act_window'].for_xml_id('link_tracker', 'action_view_click_statistics') @@ -157,39 +194,6 @@ class link_tracker(models.Model): else: return {'Error': "This filter doesn't exist."} - @api.model - def create(self, vals): - create_vals = vals.copy() - - if 'url' not in create_vals: - raise ValueError('URL field required') - else: - create_vals['url'] = VALIDATE_URL(vals['url']) - - search_domain = [] - for fname, value in create_vals.items(): - search_domain.append((fname, '=', value)) - - result = self.search(search_domain, limit=1) - - if result: - return result - - if not create_vals.get('title'): - create_vals['title'] = self._get_title_from_url(create_vals['url']) - - # Prevent the UTMs to be set by the values of UTM cookies - for (key, fname, cook) in self.env['utm.mixin'].tracking_fields(): - if fname not in create_vals: - create_vals[fname] = False - - link = super(link_tracker, self).create(create_vals) - - code = self.env['link.tracker.code'].get_random_code_string() - self.env['link.tracker.code'].sudo().create({'code': code, 'link_id': link.id}) - - return link - @api.model def get_url_from_code(self, code, context=None): code_rec = self.env['link.tracker.code'].sudo().search([('code', '=', code)]) @@ -204,13 +208,17 @@ class link_tracker(models.Model): ] -class link_tracker_code(models.Model): +class LinkTrackerCode(models.Model): _name = "link.tracker.code" - _description = 'Link Tracker Code' + _description = "Link Tracker Code" code = fields.Char(string='Short URL Code', store=True) link_id = fields.Many2one('link.tracker', 'Link', required=True, ondelete='cascade') + _sql_constraints = [ + ('code', 'unique( code )', 'Code must be unique.') + ] + @api.model def get_random_code_string(self): size = 3 @@ -222,18 +230,14 @@ class link_tracker_code(models.Model): else: return code_proposition - _sql_constraints = [ - ('code', 'unique( code )', 'Code must be unique.') - ] - -class link_tracker_click(models.Model): +class LinkTrackerClick(models.Model): _name = "link.tracker.click" _rec_name = "link_id" - _description = 'Link Tracker Click' + _description = "Link Tracker Click" - click_date = fields.Date(string='Create Date') link_id = fields.Many2one('link.tracker', 'Link', required=True, ondelete='cascade') + click_date = fields.Date(string='Create Date') ip = fields.Char(string='Internet Protocol') country_id = fields.Many2one('res.country', 'Country')