diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/website/models/website_rewrite.py | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/website/models/website_rewrite.py')
| -rw-r--r-- | addons/website/models/website_rewrite.py | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/addons/website/models/website_rewrite.py b/addons/website/models/website_rewrite.py new file mode 100644 index 00000000..31f8bc08 --- /dev/null +++ b/addons/website/models/website_rewrite.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import re +import werkzeug + +from odoo import models, fields, api, _ +from odoo.exceptions import AccessDenied, ValidationError + +import logging +_logger = logging.getLogger(__name__) + + +class WebsiteRoute(models.Model): + _rec_name = 'path' + _name = 'website.route' + _description = "All Website Route" + _order = 'path' + + path = fields.Char('Route') + + @api.model + def _name_search(self, name='', args=None, operator='ilike', limit=100, name_get_uid=None): + res = super(WebsiteRoute, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid) + if not len(res): + self._refresh() + return super(WebsiteRoute, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid) + return res + + def _refresh(self): + _logger.debug("Refreshing website.route") + ir_http = self.env['ir.http'] + tocreate = [] + paths = {rec.path: rec for rec in self.search([])} + for url, _, routing in ir_http._generate_routing_rules(self.pool._init_modules, converters=ir_http._get_converters()): + if 'GET' in (routing.get('methods') or ['GET']): + if paths.get(url): + paths.pop(url) + else: + tocreate.append({'path': url}) + + if tocreate: + _logger.info("Add %d website.route" % len(tocreate)) + self.create(tocreate) + + if paths: + find = self.search([('path', 'in', list(paths.keys()))]) + _logger.info("Delete %d website.route" % len(find)) + find.unlink() + + +class WebsiteRewrite(models.Model): + _name = 'website.rewrite' + _description = "Website rewrite" + + name = fields.Char('Name', required=True) + website_id = fields.Many2one('website', string="Website", ondelete='cascade', index=True) + active = fields.Boolean(default=True) + url_from = fields.Char('URL from', index=True) + route_id = fields.Many2one('website.route') + url_to = fields.Char("URL to") + redirect_type = fields.Selection([ + ('404', '404 Not Found'), + ('301', '301 Moved permanently'), + ('302', '302 Moved temporarily'), + ('308', '308 Redirect / Rewrite'), + ], string='Action', default="302", + help='''Type of redirect/Rewrite:\n + 301 Moved permanently: The browser will keep in cache the new url. + 302 Moved temporarily: The browser will not keep in cache the new url and ask again the next time the new url. + 404 Not Found: If you want remove a specific page/controller (e.g. Ecommerce is installed, but you don't want /shop on a specific website) + 308 Redirect / Rewrite: If you want rename a controller with a new url. (Eg: /shop -> /garden - Both url will be accessible but /shop will automatically be redirected to /garden) + ''') + + sequence = fields.Integer() + + @api.onchange('route_id') + def _onchange_route_id(self): + self.url_from = self.route_id.path + self.url_to = self.route_id.path + + @api.constrains('url_to', 'url_from', 'redirect_type') + def _check_url_to(self): + for rewrite in self: + if rewrite.redirect_type == '308': + if not rewrite.url_to: + raise ValidationError(_('"URL to" can not be empty.')) + elif not rewrite.url_to.startswith('/'): + raise ValidationError(_('"URL to" must start with a leading slash.')) + for param in re.findall('/<.*?>', rewrite.url_from): + if param not in rewrite.url_to: + raise ValidationError(_('"URL to" must contain parameter %s used in "URL from".') % param) + for param in re.findall('/<.*?>', rewrite.url_to): + if param not in rewrite.url_from: + raise ValidationError(_('"URL to" cannot contain parameter %s which is not used in "URL from".') % param) + try: + converters = self.env['ir.http']._get_converters() + routing_map = werkzeug.routing.Map(strict_slashes=False, converters=converters) + rule = werkzeug.routing.Rule(rewrite.url_to) + routing_map.add(rule) + except ValueError as e: + raise ValidationError(_('"URL to" is invalid: %s') % e) + + def name_get(self): + result = [] + for rewrite in self: + name = "%s - %s" % (rewrite.redirect_type, rewrite.name) + result.append((rewrite.id, name)) + return result + + @api.model + def create(self, vals): + res = super(WebsiteRewrite, self).create(vals) + self._invalidate_routing() + return res + + def write(self, vals): + res = super(WebsiteRewrite, self).write(vals) + self._invalidate_routing() + return res + + def unlink(self): + res = super(WebsiteRewrite, self).unlink() + self._invalidate_routing() + return res + + def _invalidate_routing(self): + # call clear_caches on this worker to reload routing table + self.env['ir.http'].clear_caches() + + def refresh_routes(self): + self.env['website.route']._refresh() |
