Renaming a page can leave a lot of broken links behind. It would be nice if the RenamePage action would, after renaming a page, create a new page with the old name containing a #redirect processing instruction so that people following old links to the page are sent to its new location.
You usually want to fix the links, not clutter your wiki with lots of redirect pages.
I do also not like this idea; 'coz you rename a page for some reason (e.g. the old name was wrong) and I do not want a search result with thousands of redirected pages. it would be better to automatically fix all relevant links to the newpagename (with a option, in the rename dialog, like update all backlinks from old to new sitename?).... but that's maybe not an easy feature. bye -- 212.203.91.124 2008-06-30 11:08:08
An user driven automated updating of links has also no gurantee to work perfectly because some pages could be acl protected.
Solution
for 1.7 (and may be 1.8):
1 --- /usr/lib/python2.5/site-packages/MoinMoin/action/RenamePage.py 2008-06-30 00:13:22 +0400
2 +++ /var/www/wiki/uneex/data/plugin/action/RenamePage.py 2009-11-28 17:07:48 +0300
3 @@ -30,6 +30,15 @@
4 subpagenames = request.rootpage.getPageList(user='', exists=1, filter=filterfn)
5 self.subpages = [pagename for pagename in subpagenames if self.request.user.may.delete(pagename)]
6
7 + form = self.request.form
8 + self.redirect = 0
9 + if 'rename_redirect' in form:
10 + try:
11 + self.redirect = int(form['rename_redirect'][0])
12 + except:
13 + pass
14 +
15 +
16 def is_allowed(self):
17 may = self.request.user.may
18 return may.write(self.pagename) and may.delete(self.pagename)
19 @@ -49,9 +58,7 @@
20 newpagename = self.request.normalizePagename(newpagename)
21 comment = form.get('comment', [u''])[0]
22 comment = wikiutil.clean_input(comment)
23 -
24 - self.page = PageEditor(self.request, self.pagename)
25 - success, msgs = self.page.renamePage(newpagename, comment)
26 + rename_redirect = self.redirect
27
28 rename_subpages = 0
29 if 'rename_subpages' in form:
30 @@ -60,6 +67,17 @@
31 except:
32 pass
33
34 +
35 + self.page = PageEditor(self.request, self.pagename)
36 + success, msgs = self.page.renamePage(newpagename, comment)
37 +
38 + if not success:
39 + return success, msgs
40 +
41 + if rename_redirect:
42 + self.page = PageEditor(self.request, self.pagename)
43 + self.page.saveText('#redirect %s' % newpagename, 0)
44 +
45 if rename_subpages and self.subpages:
46 for name in self.subpages:
47 self.page = PageEditor(self.request, name)
48 @@ -67,6 +85,11 @@
49 success_i, msg = self.page.renamePage(new_subpagename, comment)
50 msgs = "%s %s" % (msgs, msg)
51
52 + if rename_redirect and success_i:
53 + self.page = PageEditor(self.request, name)
54 + self.page.saveText('#redirect %s' % new_subpagename, 0)
55 +
56 +
57 self.newpagename = newpagename # keep there for finish
58 return success, msgs
59
60 @@ -91,7 +114,9 @@
61 'newname_label': _("New name"),
62 'comment_label': _("Optional reason for the renaming"),
63 'buttons_html': buttons_html,
64 - 'querytext': _('Really rename this page?')
65 + 'querytext': _('Really rename this page?'),
66 + 'redirect': self.redirect,
67 + 'redirect_label': _('Create redirect for renamed pages?'),
68 }
69
70 return '''
71 @@ -107,6 +132,11 @@
72 <class="label"><subpage> %(subpage)s</subpage>
73 </dd>
74 </tr>
75 + <tr>
76 + <dd>
77 + %(redirect_label)s<input type="checkbox" name="rename_redirect" value="1" %(redirect)s>
78 + </dd>
79 + </tr>
80 </table>
81 <table>
82 <tr>
83 @@ -136,9 +166,19 @@
84 'newname_label': _("New name"),
85 'comment_label': _("Optional reason for the renaming"),
86 'buttons_html': buttons_html,
87 + 'redirect': self.redirect,
88 + 'redirect_label': _('Create redirect for renamed page?'),
89 }
90 return '''
91 <table>
92 + </tr>
93 + <tr>
94 + <dd>
95 + %(redirect_label)s<input type="checkbox" name="rename_redirect" value="1" %(redirect)s>
96 + </dd>
97 + </tr>
98 +</table>
99 +<table>
100 <tr>
101 <td class="label"><label>%(newname_label)s</label></td>
102 <td class="content">
patch for 1.9 hg:
1 # HG changeset patch
2 # User Eugene Syromyatnikov <evgsyr@gmail.com>
3 # Date 1259423676 -10800
4 # Node ID b9a8cfae00acd2b142c23f8abbc9fb8a06116aef
5 # Parent 5aef81c6ba8d2e6d560001a3f535aaa26e815edd
6 Rename page action: added redirect checkbox, fixed bug with renaming subpages to inaccesible names during renaming to page empty name
7
8 diff -r 5aef81c6ba8d -r b9a8cfae00ac MoinMoin/action/RenamePage.py
9 --- a/MoinMoin/action/RenamePage.py Mon Nov 16 13:31:48 2009 +0300
10 +++ b/MoinMoin/action/RenamePage.py Sat Nov 28 18:54:36 2009 +0300
11 @@ -29,6 +29,7 @@
12 filterfn = re.compile(ur"^%s/.*$" % re.escape(pagename), re.U).match
13 subpagenames = request.rootpage.getPageList(user='', exists=1, filter=filterfn)
14 self.subpages = [pagename for pagename in subpagenames if self.request.user.may.delete(pagename)]
15 + self.redirect = int(self.request.form.get('rename_redirect', '0'))
16
17 def is_allowed(self):
18 may = self.request.user.may
19 @@ -49,22 +50,32 @@
20 newpagename = wikiutil.normalize_pagename(newpagename, self.cfg)
21 comment = form.get('comment', u'')
22 comment = wikiutil.clean_input(comment)
23 + rename_redirect = self.redirect
24 + rename_subpages = int(self.request.form.get('rename_subpages', '0'))
25
26 self.page = PageEditor(self.request, self.pagename)
27 success, msgs = self.page.renamePage(newpagename, comment)
28
29 - rename_subpages = 0
30 - try:
31 - rename_subpages = int(form['rename_subpages'])
32 - except:
33 - pass
34 + if not success:
35 + return success, msgs
36 +
37 + if rename_redirect:
38 + self.page = PageEditor(self.request, self.pagename)
39 + self.page.saveText('#redirect %s' % newpagename, 0)
40
41 if rename_subpages and self.subpages:
42 + msgs = []
43 for name in self.subpages:
44 self.page = PageEditor(self.request, name)
45 new_subpagename = name.replace(self.pagename, newpagename, 1)
46 success_i, msg = self.page.renamePage(new_subpagename, comment)
47 - msgs = "%s %s" % (msgs, msg)
48 + msgs.append(msg)
49 +
50 + if rename_redirect and success_i:
51 + self.page = PageEditor(self.request, name)
52 + self.page.saveText('#redirect %s' % new_subpagename, 0)
53 + msgs = ' '.join([msg for msg in msgs if msg != None])
54 +
55
56 self.newpagename = newpagename # keep there for finish
57 return success, msgs
58 @@ -88,7 +99,9 @@
59 'newname_label': _("New name"),
60 'comment_label': _("Optional reason for the renaming"),
61 'buttons_html': buttons_html,
62 - 'querytext': _('Really rename this page?')
63 + 'querytext': _('Really rename this page?'),
64 + 'redirect': self.redirect,
65 + 'redirect_label': _('Create redirect for renamed pages?'),
66 }
67
68 return '''
69 @@ -104,6 +117,11 @@
70 <class="label"><subpage> %(subpage)s</subpage>
71 </dd>
72 </tr>
73 + <tr>
74 + <dd>
75 + %(redirect_label)s<input type="checkbox" name="rename_redirect" value="1" %(redirect)s>
76 + </dd>
77 + </tr>
78 </table>
79 <table>
80 <tr>
81 @@ -133,10 +151,19 @@
82 'newname_label': _("New name"),
83 'comment_label': _("Optional reason for the renaming"),
84 'buttons_html': buttons_html,
85 + 'redirect': self.redirect,
86 + 'redirect_label': _('Create redirect for renamed page?'),
87 }
88 return '''
89 <table>
90 <tr>
91 + <dd>
92 + %(redirect_label)s<input type="checkbox" name="rename_redirect" value="1" %(redirect)s>
93 + </dd>
94 + </tr>
95 +</table>
96 +<table>
97 + <tr>
98 <td class="label"><label>%(newname_label)s</label></td>
99 <td class="content">
100 <input type="text" name="newpagename" value="%(pagename)s" size="80">
Edit conflict - other version:
version of patch with config option:
1 diff -r c800980890aa MoinMoin/action/RenamePage.py
2 --- a/MoinMoin/action/RenamePage.py Fri Jan 15 17:35:20 2010 +0300
3 +++ b/MoinMoin/action/RenamePage.py Fri Jan 15 19:20:24 2010 +0300
4 @@ -29,6 +29,8 @@
5 filterfn = re.compile(ur"^%s/.*$" % re.escape(pagename), re.U).match
6 subpagenames = request.rootpage.getPageList(user='', exists=1, filter=filterfn)
7 self.subpages = [pagename for pagename in subpagenames if self.request.user.may.delete(pagename)]
8 + self.redirect = int(self.request.form.get('rename_redirect', '0'))
9 + self.allow_redirect = request.cfg.allow_auto_redirect_creation_on_renaming
10
11 def is_allowed(self):
12 may = self.request.user.may
13 @@ -49,6 +51,8 @@
14 newpagename = wikiutil.normalize_pagename(newpagename, self.cfg)
15 comment = form.get('comment', u'')
16 comment = wikiutil.clean_input(comment)
17 + rename_redirect = self.redirect
18 + rename_subpages = int(self.request.form.get('rename_subpages', '0'))
19
20 self.page = PageEditor(self.request, self.pagename)
21 success, msgs = self.page.renamePage(newpagename, comment)
22 @@ -56,18 +60,23 @@
23 if not success:
24 return success, msgs
25
26 - rename_subpages = 0
27 - try:
28 - rename_subpages = int(form['rename_subpages'])
29 - except:
30 - pass
31 + msgs = [msgs]
32 +
33 + if self.allow_redirect and rename_redirect:
34 + self.page = PageEditor(self.request, self.pagename)
35 + self.page.saveText('#redirect %s' % newpagename, 0)
36
37 if rename_subpages and self.subpages:
38 for name in self.subpages:
39 self.page = PageEditor(self.request, name)
40 new_subpagename = name.replace(self.pagename, newpagename, 1)
41 success_i, msg = self.page.renamePage(new_subpagename, comment)
42 - msgs = "%s %s" % (msgs, msg)
43 + msgs.append(msg)
44 +
45 + if self.allow_redirect and rename_redirect and success_i:
46 + self.page = PageEditor(self.request, name)
47 + self.page.saveText('#redirect %s' % new_subpagename, 0)
48 + msgs = ' '.join([msg for msg in msgs if msg != None])
49
50 self.newpagename = newpagename # keep there for finish
51 return success, msgs
52 @@ -82,6 +91,14 @@
53 def get_form_html(self, buttons_html):
54 _ = self._
55 if self.subpages:
56 + if self.allow_redirect:
57 + redirect_html = '<tr><dd>%(redirect_label)s<input type="checkbox" name="rename_redirect" value="1" %(redirect)s></dd></tr>' % {
58 + 'redirect': self.redirect,
59 + 'redirect_label': _('Create redirect for renamed page(s)?'),
60 + }
61 + else:
62 + redirect_html = ''
63 +
64 subpages = ' '.join(self.subpages)
65 d = {
66 'subpage': subpages,
67 @@ -91,7 +108,8 @@
68 'newname_label': _("New name"),
69 'comment_label': _("Optional reason for the renaming"),
70 'buttons_html': buttons_html,
71 - 'querytext': _('Really rename this page?')
72 + 'querytext': _('Really rename this page?'),
73 + 'redirect_html': redirect_html,
74 }
75
76 return '''
77 @@ -107,6 +125,7 @@
78 <class="label"><subpage> %(subpage)s</subpage>
79 </dd>
80 </tr>
81 + %(redirect_html)s
82 </table>
83 <table>
84 <tr>
85 @@ -131,13 +150,23 @@
86 ''' % d
87
88 else:
89 + if self.allow_redirect:
90 + redirect_html = '<table><tr><dd>%(redirect_label)s<input type="checkbox" name="rename_redirect" value="1" %(redirect)s></dd></tr></table>' % {
91 + 'redirect': self.redirect,
92 + 'redirect_label': _('Create redirect for renamed page?'),
93 + }
94 + else:
95 + redirect_html = ''
96 +
97 d = {
98 'pagename': wikiutil.escape(self.pagename, True),
99 'newname_label': _("New name"),
100 'comment_label': _("Optional reason for the renaming"),
101 'buttons_html': buttons_html,
102 + 'redirect_html': redirect_html,
103 }
104 return '''
105 +%(redirect_html)s
106 <table>
107 <tr>
108 <td class="label"><label>%(newname_label)s</label></td>
109 diff -r c800980890aa MoinMoin/config/multiconfig.py
110 --- a/MoinMoin/config/multiconfig.py Fri Jan 15 17:35:20 2010 +0300
111 +++ b/MoinMoin/config/multiconfig.py Fri Jan 15 19:20:24 2010 +0300
112 @@ -1047,6 +1047,8 @@
113 "if True, do a reverse DNS lookup on page SAVE. If your DNS is broken, set this to False to speed up SAVE."),
114 ('log_timing', False,
115 "if True, add timing infos to the log output to analyse load conditions"),
116 + ('allow_auto_redirect_creation_on_renaming', False,
117 + "if True, option of creating redirect pages on place of renamed will be proposed on page renaming."),
118
119 # some dangerous mimetypes (we don't use "content-disposition: inline" for them when a user
120 # downloads such attachments, because the browser might execute e.g. Javascript contained
These patches also fix MoinMoinBugs/RenamePageDestroysSubPageNaming.
Discussion
Sometimes I rename pages to e.g. DeleteThisPage + name because it is an easy way to remove also by a script all its attachments. And i can create immediatly afterwards a new page with the same old name. At that time I don't want inplace redirects.
If one renames by xmlrpc you have the old situation. So implementing this at the action level may not be the best place.
The redirect page line may cause acl problems. Because if the renamed page has had an acl line and the placeholder does not. And if the new page which does have the redirect line on it and is not potected against editing one could easily replace the redirect by some important text. And by this the placeholder concept is broken.
I would prefer a different solution. Not sure if that can work better: Currently we save on the page which was renamed its old name. At least with xapian it should be possible to solve it differently too. xapian could index the old name of the page at rename time. And if a page does not exists one can get shown the creation dialog and the renamed name together. If one selects the renamed page and he can edit the page it would be nice to have an automated s/old/new of the link name then.
- Well, this patch only adds ability (which can be turned on or off by wiki configuration) to create redirects, it isn't forces creation of them. The acl stuff is a mess anyway, because person who does renaming can have read/write/delete privs, but no admin, for example. The same thing applies to redirect page. May be, the best solution is to try create redirect with acl, then without it and give up at last.
-- EugeneSyromyatnikov 2010-01-15 16:49:39
Status
Added in http://hg.moinmo.in/moin/1.9/rev/354356b125b4