summaryrefslogtreecommitdiff
path: root/addons/website/models/website_rewrite.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/website/models/website_rewrite.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/website/models/website_rewrite.py')
-rw-r--r--addons/website/models/website_rewrite.py132
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()