Ticket #1106: rename_with_page_save.diff
| File rename_with_page_save.diff, 29.2 KB (added by shookie@…, 2 years ago) |
|---|
-
trac/admin/tests/console-tests.txt
diff --git a/trac/admin/tests/console-tests.txt b/trac/admin/tests/console-tests.txt index e05f6f5..a3dcc00 100644
a b Available actions: 115 115 TICKET_EDIT_CC, TICKET_EDIT_COMMENT, TICKET_EDIT_DESCRIPTION, 116 116 TICKET_MODIFY, TICKET_VIEW, TIMELINE_VIEW, TRAC_ADMIN, 117 117 VERSIONCONTROL_ADMIN, WIKI_ADMIN, WIKI_CREATE, WIKI_DELETE, WIKI_MODIFY, 118 WIKI_ VIEW118 WIKI_RENAME, WIKI_VIEW 119 119 120 120 ===== test_permission_add_one_action_ok ===== 121 121 … … Available actions: 150 150 TICKET_EDIT_CC, TICKET_EDIT_COMMENT, TICKET_EDIT_DESCRIPTION, 151 151 TICKET_MODIFY, TICKET_VIEW, TIMELINE_VIEW, TRAC_ADMIN, 152 152 VERSIONCONTROL_ADMIN, WIKI_ADMIN, WIKI_CREATE, WIKI_DELETE, WIKI_MODIFY, 153 WIKI_ VIEW153 WIKI_RENAME, WIKI_VIEW 154 154 155 155 ===== test_permission_add_multiple_actions_ok ===== 156 156 … … Available actions: 186 186 TICKET_EDIT_CC, TICKET_EDIT_COMMENT, TICKET_EDIT_DESCRIPTION, 187 187 TICKET_MODIFY, TICKET_VIEW, TIMELINE_VIEW, TRAC_ADMIN, 188 188 VERSIONCONTROL_ADMIN, WIKI_ADMIN, WIKI_CREATE, WIKI_DELETE, WIKI_MODIFY, 189 WIKI_ VIEW189 WIKI_RENAME, WIKI_VIEW 190 190 191 191 ===== test_permission_remove_one_action_ok ===== 192 192 … … Available actions: 220 220 TICKET_EDIT_CC, TICKET_EDIT_COMMENT, TICKET_EDIT_DESCRIPTION, 221 221 TICKET_MODIFY, TICKET_VIEW, TIMELINE_VIEW, TRAC_ADMIN, 222 222 VERSIONCONTROL_ADMIN, WIKI_ADMIN, WIKI_CREATE, WIKI_DELETE, WIKI_MODIFY, 223 WIKI_ VIEW223 WIKI_RENAME, WIKI_VIEW 224 224 225 225 ===== test_permission_remove_multiple_actions_ok ===== 226 226 … … Available actions: 254 254 TICKET_EDIT_CC, TICKET_EDIT_COMMENT, TICKET_EDIT_DESCRIPTION, 255 255 TICKET_MODIFY, TICKET_VIEW, TIMELINE_VIEW, TRAC_ADMIN, 256 256 VERSIONCONTROL_ADMIN, WIKI_ADMIN, WIKI_CREATE, WIKI_DELETE, WIKI_MODIFY, 257 WIKI_ VIEW257 WIKI_RENAME, WIKI_VIEW 258 258 259 259 ===== test_component_list_ok ===== 260 260 -
trac/attachment.py
diff --git a/trac/attachment.py b/trac/attachment.py index 77bd09f..3de5389 100644
a b class Attachment(object): 274 274 except OSError, e: 275 275 env.log.error("Can't delete attachment directory %s: %s", 276 276 attachment_dir, exception_to_unicode(e, traceback=True)) 277 278 @classmethod 279 def reparent_all(cls, env, old_realm, old_id, new_realm, new_id, db=None): 280 """Reparent all attachments of a given resource to another resource. 281 282 :param old_realm: old parent's realm 283 :param old_id: old parent's id 284 :param new_realm: new parent's realm 285 :param new_id: new parent's id 286 :param env: the environent 287 :param db: the database connection 288 """ 289 old_dir = os.path.join(os.path.normpath(env.path), 'attachments', 290 old_realm, old_id) 291 if not os.path.exists(old_dir): 292 return 293 294 new_dir = os.path.join(os.path.normpath(env.path), 'attachments', 295 new_realm, new_id) 296 297 @with_transaction(env, db) 298 def do_reparent(db): 299 cursor = db.cursor() 300 cursor.execute(""" 301 SELECT filename FROM attachment 302 WHERE type=%s AND id=%s 303 """, (old_realm, old_id)) 304 305 renames = [] 306 for filename, in cursor: 307 old_filename = os.path.join(old_dir, filename) 308 new_filename = os.path.join(new_dir, filename) 309 if os.path.exists(new_filename): 310 raise TracError(_("Can't reparent attachment '%(att)s' as " 311 "it already exists in %(realm)s:%(id)s", 312 att=new_filename, 313 realm=new_realm, id=new_id)) 314 renames.append((old_filename, new_filename)) 315 316 try: 317 if not os.path.exists(new_dir): 318 os.makedirs(new_dir) 319 except OSError, e: 320 env.log.error("Can't create attachment directory '%s'", 321 new_dir, exc_info=True) 322 raise TracError(_("Can't create attachment folder for " 323 "%(realm)s:%(id)s: %(err)", 324 realm=new_realm, id=new_id, err=e)) 325 326 for old_filename, new_filename in renames: 327 try: 328 os.rename(old_filename, new_filename) 329 except OSError, e: 330 env.log.error("Can't move attachment from '%s' to '%s'", 331 old_filename, new_filename, exc_info=True) 332 raise TracError(_("Can't move attachment '%(att)s'", 333 att=os.path.basename(new_filename))) 334 cursor.execute(""" 335 UPDATE attachment SET type=%s, id=%s 336 WHERE type=%s AND id=%s 337 """, (new_realm, new_id, old_realm, old_id)) 338 339 env.log.info('Attachments reparented to: %s:%s', new_realm, new_id) 340 341 342 return 277 343 278 344 def open(self): 279 345 self.env.log.debug('Trying to open attachment at %s', self.path) -
trac/db_default.py
diff --git a/trac/db_default.py b/trac/db_default.py index 2c9e1a6..7d57acb 100644
a b schema = [ 38 38 Table('system', key='name')[ 39 39 Column('name'), 40 40 Column('value')], 41 Table('urlmap', key='key')[ 42 Column('key'), 43 Column('value')], 41 44 Table('permission', key=('username', 'action'))[ 42 45 Column('username'), 43 46 Column('action')], … … def get_data(db): 394 397 ('name', 'value'), 395 398 (('database_version', str(db_version)), 396 399 ('initial_database_version', str(db_version)))), 400 ('urlmap', 401 ('key', 'value'), 402 (('WikiStart', 'WikiStart'), 403 ('TitleIndex', 'TitleIndex'), 404 ('TracGuide', 'TracGuide'), 405 ('TracInstall', 'TracInstall'), 406 ('InterMapTxt', 'InterMapTxt'))), 397 407 ('report', 398 408 ('author', 'title', 'query', 'description'), 399 409 __mkreports(get_reports(db)))) -
trac/env.py
diff --git a/trac/env.py b/trac/env.py index 50babb3..0ec5b47 100644
a b class Environment(Component, ComponentManager): 384 384 row = cursor.fetchone() 385 385 return row and int(row[0]) 386 386 387 def get_urlmap(self, key, db=None, reverse=False, keycheck=False): 388 """Return the real path of some fixed pages trac expects, 389 but cannot rely on existing because 390 renaming and deleting pages is possible. 391 """ 392 if not db: 393 db = self.get_db_cnx() 394 cursor = db.cursor() 395 k, v = ('key', 'value') 396 if keycheck: 397 k, v = k, k 398 if reverse: 399 k, v = v, k 400 q = "SELECT %s FROM urlmap WHERE %s=" % (v, k) 401 cursor.execute(q + "%s", (key,)) 402 row = cursor.fetchone() 403 return row and row[0] 404 387 405 def setup_config(self, load_defaults=False): 388 406 """Load the configuration file.""" 389 407 self.config = Configuration(os.path.join(self.path, 'conf', -
trac/htdocs/css/wiki.css
diff --git a/trac/htdocs/css/wiki.css b/trac/htdocs/css/wiki.css index 091f2f6..f109783 100644
a b 42 42 #changeinfo br { clear: left } 43 43 #changeinfo .options { padding: 0 0 1em 1em } 44 44 #changeinfo .options, #changeinfo .buttons { clear: left } 45 #delete, # save { margin-left: 6em }45 #delete, #rename, #save { margin-left: 6em } 46 46 #preview { 47 47 background: #f4f4f4 url(../draft.png); 48 48 margin: 1em 0 2em; -
trac/tests/functional/tester.py
diff --git a/trac/tests/functional/tester.py b/trac/tests/functional/tester.py index b983e1b..24a06e5 100755
a b class FunctionalTester(object): 176 176 tc.formvalue('attachment', 'replace', True) 177 177 tc.submit() 178 178 tc.url(self.url + '/attachment/ticket/%s/$' % ticketid) 179 return tempfilename 179 180 180 181 def clone_ticket(self, ticketid): 181 182 """Create a clone of the given ticket id using the clone button.""" … … class FunctionalTester(object): 232 233 tc.formvalue('attachment', 'description', random_sentence()) 233 234 tc.submit() 234 235 tc.url(self.url + '/attachment/wiki/%s/$' % name) 236 return tempfilename 235 237 236 238 def create_milestone(self, name=None, due=None): 237 239 """Creates the specified milestone, with a random name if none is -
trac/wiki/api.py
diff --git a/trac/wiki/api.py b/trac/wiki/api.py index 69dbed9..eaba52d 100644
a b class IWikiChangeListener(Interface): 42 42 def wiki_page_deleted(page): 43 43 """Called when a page has been deleted.""" 44 44 45 def wiki_page_renamed(page,old_page_name): 46 """Called when a page has been renamed in-place.""" 47 45 48 def wiki_page_version_deleted(page): 46 49 """Called when a version of a page has been deleted.""" 47 50 … … class WikiSystem(Component): 290 293 pagename, version = pagename.split('@', 1) 291 294 if version and query: 292 295 query = '&' + query[1:] 293 pagename = pagename.rstrip('/') or 'WikiStart'296 pagename = pagename.rstrip('/') or self.env.get_urlmap('WikiStart') 294 297 referrer = '' 295 298 if formatter.resource and formatter.resource.realm == 'wiki': 296 299 referrer = formatter.resource.id -
trac/wiki/model.py
diff --git a/trac/wiki/model.py b/trac/wiki/model.py index 6dc95b5..d302dc8 100644
a b class WikiPage(object): 91 91 if version is None: 92 92 # Delete a wiki page completely 93 93 cursor.execute("DELETE FROM wiki WHERE name=%s", (self.name,)) 94 mapped = self.env.get_urlmap(self.name, db=db, reverse=True) 95 if mapped: 96 cursor.execute("""UPDATE urlmap SET value=NULL 97 WHERE key=%s""", (mapped,)) 98 94 99 self.env.log.info('Deleted page %s' % self.name) 95 100 else: 96 101 # Delete only a specific page version … … class WikiPage(object): 135 140 """, (self.name, self.version + 1, to_utimestamp(t), 136 141 author, remote_addr, self.text, comment, 137 142 self.readonly)) 143 mappable = self.env.get_urlmap(self.name, db=db, keycheck=True) 144 if mappable: 145 cursor.execute("""UPDATE urlmap SET value=%s 146 WHERE key=%s""", (self.name, self.name)) 138 147 self.version += 1 139 148 self.resource = self.resource(version=self.version) 140 149 else: … … class WikiPage(object): 158 167 self.old_readonly = self.readonly 159 168 self.old_text = self.text 160 169 170 def rename(self, new_name, db=None): 171 """Rename wiki page in-place, keeping the history intact. 172 Renaming a page this way will eventually leave dangling references 173 to the old page - which litterally doesn't exist anymore. 174 """ 175 assert self.exists, 'Cannot rename non-existent page' 176 177 old_name = self.name 178 179 @with_transaction(self.env, db) 180 def do_rename(db): 181 cursor = db.cursor() 182 new_page = WikiPage(self.env, new_name, version=None, db=db) 183 if new_page.exists: 184 raise TracError(_("Can't rename to existing %(nn)s page.", 185 nn=new_name)) 186 187 cursor.execute("UPDATE wiki SET name=%s WHERE name=%s", 188 (new_name, old_name)) 189 mapped = self.env.get_urlmap(old_name, db=db, reverse=True) 190 mappable = self.env.get_urlmap(new_name, db=db, keycheck=True) 191 192 if mapped or mappable: 193 cursor.execute("""UPDATE urlmap SET value=%s 194 WHERE key=%s""", (new_name, mapped or mappable)) 195 self.name = new_name 196 self._fetch(self.name, None, db) 197 198 from trac.attachment import Attachment 199 Attachment.reparent_all(self.env, 'wiki', old_name, 200 'wiki', self.name, db) 201 202 self.env.log.info('Renamed page %s in-place to %s', old_name, new_name) 203 204 for listener in WikiSystem(self.env).change_listeners: 205 if hasattr(listener, 'wiki_page_renamed'): 206 listener.wiki_page_renamed(self, old_name) 207 208 161 209 def get_history(self, db=None): 162 210 if not db: 163 211 db = self.env.get_db_cnx() -
new file trac/wiki/templates/wiki_rename.html
diff --git a/trac/wiki/templates/wiki_rename.html b/trac/wiki/templates/wiki_rename.html new file mode 100644 index 0000000..f00b807
- + 1 <!DOCTYPE html 2 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 4 <html xmlns="http://www.w3.org/1999/xhtml" 5 xmlns:py="http://genshi.edgewall.org/" 6 xmlns:xi="http://www.w3.org/2001/XInclude"> 7 <xi:include href="layout.html" /> 8 <head> 9 <title>$title</title> 10 </head> 11 12 <body> 13 <div id="content" class="wiki" 14 py:with=" 15 current_href = href.wiki(page.name); 16 "> 17 <h1>${_('Rename')} <a href="$current_href">$page.name</a></h1> 18 <form action="$current_href" method="post"> 19 <p> 20 <input type="hidden" name="action" value="rename" /> 21 <strong>Renaming the page will rename all existing versions 22 of the page in place. <br /> 23 The history of the renamed page will be exactly the same as the one 24 of the original page.</strong> 25 <br /> 26 <p> 27 <label for="new_name">New name:</label> 28 <input type="text" id="new_name" name="new_name" size="40" value="$page.name" /> 29 </p> 30 <br /> 31 <fieldset id="rename_options" class="group"> 32 <legend>${_('Rename')} ${_('Options')}</legend> 33 <input type="checkbox" id="leave_redirection" name="leave_redirection"/> 34 <label for="leave_redirection">Leave a redirection to the new page.</label> 35 <br /> 36 If you choose to leave a redirection, this will 37 re-create the $page.name page with a link pointing to the new 38 page. 39 </fieldset> 40 </p> 41 <div class="buttons"> 42 <input type="submit" name="cancel" value="${_('Cancel')}" /> 43 <input type="submit" value="${_('Rename')} $page.name" /> 44 </div> 45 </form> 46 </div> 47 </body> 48 </html> -
trac/wiki/templates/wiki_view.html
diff --git a/trac/wiki/templates/wiki_view.html b/trac/wiki/templates/wiki_view.html index 0715fbe..17880bd 100644
a b 71 71 72 72 <py:with vars="modify_perm = 'WIKI_MODIFY' in perm(page.resource); 73 73 delete_perm = 'WIKI_DELETE' in perm(page.resource); 74 admin_perm = 'WIKI_ADMIN' in perm(page.resource)"> 74 admin_perm = 'WIKI_ADMIN' in perm(page.resource); 75 rename_perm = 'WIKI_RENAME' in perm(page.resource)"> 75 76 <py:if test="admin_perm or (not page.readonly and (modify_perm or delete_perm))"> 76 77 <div class="buttons"> 77 78 <py:if test="modify_perm"> … … 101 102 ${attach_file_form(attachments)} 102 103 </py:if> 103 104 </py:if> 105 <py:if test="page.exists and rename_perm"> 106 <form method="get" action="${href.wiki(page.name)}" id="rename"> 107 <div> 108 <input type="hidden" name="action" value="rename" /> 109 <input type="submit" value="${_('Rename page')}" /> 110 </div> 111 </form> 112 </py:if> 104 113 <py:if test="page.exists and delete_perm"> 105 114 <form method="get" action="${href.wiki(page.name)}"> 106 115 <div id="delete"> -
trac/wiki/tests/functional.py
diff --git a/trac/wiki/tests/functional.py b/trac/wiki/tests/functional.py index bd85ec8..07a290e 100755
a b class TestWiki(FunctionalTwillTestCaseSetup): 12 12 self._tester.attach_file_to_wiki(pagename) 13 13 14 14 15 class TestWikiRename(FunctionalTwillTestCaseSetup): 16 def runTest(self): 17 """Test for simple wiki rename""" 18 pagename = random_unique_camel() 19 self._tester.create_wiki_page(pagename) 20 self._tester.rename_wiki_page(pagename) 21 attachment = self._tester.attach_file_to_wiki(pagename) 22 base_url = self._tester.url 23 page_url = base_url + "/wiki/" + pagename 24 25 def click_rename(): 26 tc.formvalue('rename', 'action', 'rename') 27 tc.submit() 28 tc.url(page_url+r'\?action=rename') 29 tc.find("New name:") 30 31 tc.go(page_url) 32 tc.find("Rename page") 33 click_rename() 34 # attempt to rename the page to the current page name ... 35 tc.formvalue(page_url, 'new_name', 'rename') 36 tc.submit('rename') 37 tc.url(page_url) 38 tc.find("New name must be different from old name.") 39 # attempt to rename the page to an existing page name ... 40 tc.formvalue(page_url, 'new_name', 'WikiStart') 41 tc.submit('rename') 42 tc.url(page_url) 43 tc.find("Trac Error") 44 tc.find("Can't rename to existing WikiStart page") 45 # correct rename to new page name (old page replaced by a redirection) 46 tc.go(page_url) 47 click_rename() 48 newpagename = pagename+'Renamed' 49 tc.formvalue(page_url, 'new_name', newpagename) 50 tc.formvalue(page_url, 'leave_redirection', True) # the default 51 tc.submit('rename') 52 # check redirection page 53 tc.url(page_url) 54 tc.find("See.*/wiki/"+newpagename) 55 # check whether attachment exists on the new page but not on old page 56 tc.go(base_url+'/attachment/wiki/'+newpagename+'/'+attachment) 57 tc.notfind("Error: Invalid Attachment") 58 tc.go(base_url+'/attachment/wiki/'+pagename+'/'+attachment) 59 tc.find("Error: Invalid Attachment") 60 # rename again to another new page name (this time, no redirection) 61 tc.go(page_url) 62 click_rename() 63 newpagename = pagename+'RenamedAgain' 64 tc.formvalue(page_url, 'new_name', newpagename) 65 tc.formvalue(page_url, 'leave_redirection', False) 66 tc.submit('rename') 67 tc.url(base_url + "/wiki/" + newpagename) 68 # this time, the original page is gone 69 tc.go(page_url) 70 tc.url(page_url) 71 tc.find("Describe %s here" % pagename) 72 73 74 15 75 class RegressionTestTicket4812(FunctionalTwillTestCaseSetup): 16 76 def runTest(self): 17 77 """Test for regression of http://trac.edgewall.org/ticket/4812""" -
trac/wiki/tests/model.py
diff --git a/trac/wiki/tests/model.py b/trac/wiki/tests/model.py index e4fde47..13f84b7 100644
a b 1 1 from datetime import datetime 2 import tempfile 2 3 import unittest 3 4 5 from trac.attachment import Attachment 4 6 from trac.core import * 5 7 from trac.test import EnvironmentStub 6 8 from trac.util.datefmt import utc, to_utimestamp … … class TestWikiChangeListener(Component): 14 16 self.changed = [] 15 17 self.deleted = [] 16 18 self.deleted_version = [] 19 self.renamed = {} 17 20 18 21 def wiki_page_added(self, page): 19 22 self.added.append(page) … … class TestWikiChangeListener(Component): 27 30 def wiki_page_version_deleted(self, page): 28 31 self.deleted_version.append(page) 29 32 33 def wiki_page_renamed(self, page, old_page_name): 34 self.renamed[old_page_name] = page 35 30 36 31 37 class WikiPageTestCase(unittest.TestCase): 32 38 … … class WikiPageTestCase(unittest.TestCase): 194 200 listener = TestWikiChangeListener(self.env) 195 201 self.assertEqual(page, listener.deleted[0]) 196 202 203 def test_rename_page(self): 204 cursor = self.db.cursor() 205 data = (1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0) 206 cursor.execute("INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)", 207 ('TestPage',) + data) 208 209 page = WikiPage(self.env, 'TestPage') 210 211 attachment = Attachment(self.env, 'wiki', 'TestPage') 212 attachment.insert('foo.txt', tempfile.TemporaryFile(), 0, 1) 213 214 page.rename('PageRenamed') 215 216 cursor.execute("SELECT version,time,author,ipnr,text,comment," 217 "readonly FROM wiki WHERE name=%s", ('PageRenamed',)) 218 self.assertEqual(data, cursor.fetchone()) 219 self.assertEqual(None, cursor.fetchone()) 220 221 attachments = Attachment.select(self.env, 'wiki', 'PageRenamed') 222 self.assertEqual('foo.txt', attachments.next().filename) 223 self.assertRaises(StopIteration, attachments.next) 224 Attachment.delete_all(self.env, 'wiki', 'PageRenamed', self.db) 225 226 227 old_page = WikiPage(self.env, 'TestPage') 228 229 cursor.execute("SELECT version,time,author,ipnr,text,comment," 230 "readonly FROM wiki WHERE name=%s", ('TestPage',)) 231 self.assertEqual(None, cursor.fetchone()) 232 233 listener = TestWikiChangeListener(self.env) 234 self.assertEqual({'TestPage': page}, listener.renamed) 235 236 def test_sys_pages(self): 237 cursor = self.db.cursor() 238 cursor.execute("INSERT INTO urlmap VALUES(%s, NULL)", 239 ('WikiStart',)) 240 241 page = WikiPage(self.env) 242 page.name = 'WikiStart' 243 page.text = 'Bla bla' 244 t = datetime(2001, 1, 1, 1, 1, 1, 0, utc) 245 page.save('joe', 'Testing', '::1', t) 246 247 cursor.execute("SELECT key, value FROM urlmap WHERE key=%s", ('WikiStart',)) 248 self.assertEqual(('WikiStart', 'WikiStart'), cursor.fetchone()) 249 250 page.rename('Home') 251 cursor.execute("SELECT key, value FROM urlmap WHERE key=%s", ('WikiStart',)) 252 self.assertEqual(('WikiStart', 'Home'), cursor.fetchone()) 253 254 page.delete() 255 cursor.execute("SELECT key, value FROM urlmap WHERE key=%s", ('WikiStart',)) 256 self.assertEqual(('WikiStart', None), cursor.fetchone()) 197 257 198 258 def suite(): 199 259 return unittest.makeSuite(WikiPageTestCase, 'test') -
trac/wiki/web_ui.py
diff --git a/trac/wiki/web_ui.py b/trac/wiki/web_ui.py index 6e3bcde..7bcda70 100644
a b class WikiModule(Component): 93 93 # IPermissionRequestor methods 94 94 95 95 def get_permission_actions(self): 96 actions = ['WIKI_CREATE', 'WIKI_DELETE', 'WIKI_MODIFY', 'WIKI_ VIEW']96 actions = ['WIKI_CREATE', 'WIKI_DELETE', 'WIKI_MODIFY', 'WIKI_RENAME', 'WIKI_VIEW'] 97 97 return actions + [('WIKI_ADMIN', actions)] 98 98 99 99 # IRequestHandler methods … … class WikiModule(Component): 107 107 108 108 def process_request(self, req): 109 109 action = req.args.get('action', 'view') 110 pagename = req.args.get('page', 'WikiStart') 110 pagename = req.args.get('page', self.env.get_urlmap('WikiStart')) 111 pagename = pagename or 'WikiStart' 111 112 version = req.args.get('version') 112 113 old_version = req.args.get('old_version') 113 114 … … class WikiModule(Component): 145 146 return self._render_editor(req, page, action, has_collision) 146 147 elif action == 'delete': 147 148 self._do_delete(req, versioned_page) 149 elif action == 'rename': 150 return self._do_rename(req, page) 148 151 elif action == 'diff': 149 152 get_diff_options(req) 150 153 req.redirect(req.href.wiki(versioned_page.name, action='diff', 151 154 old_version=old_version)) 152 155 elif action == 'delete': 153 return self._render_confirm(req, versioned_page) 156 return self._render_confirm_delete(req, versioned_page) 157 elif action == 'rename': 158 return self._render_confirm_rename(req, page) 154 159 elif action == 'edit': 155 160 return self._render_editor(req, versioned_page) 156 161 elif action == 'diff': … … class WikiModule(Component): 245 250 old_version = int(req.args.get('old_version', 0)) or version 246 251 247 252 @with_transaction(self.env) 248 def do_ transaction(db):253 def do_delete(db): 249 254 if version and old_version and version > old_version: 250 255 # delete from `old_version` exclusive to `version` inclusive: 251 256 for v in range(old_version, version): … … class WikiModule(Component): 269 274 version=version, name=page.name)) 270 275 req.redirect(req.href.wiki(page.name)) 271 276 277 def _do_rename(self, req, page): 278 if page.readonly: 279 req.perm(page.resource).require('WIKI_ADMIN') 280 else: 281 req.perm(page.resource).require('WIKI_RENAME') 282 283 if 'cancel' in req.args: 284 req.redirect(get_resource_url(self.env, page.resource, req.href)) 285 286 new_name = req.args.get('new_name', '').rstrip('/') 287 old_name = page.name 288 old_version = page.version 289 leave_redirection = req.args.get('leave_redirection') 290 291 # verify input parameters 292 warn = None 293 if not new_name: 294 warn = _("New name is mandatory for a rename.") 295 elif new_name == old_name: 296 warn = _("New name must be different from old name.") 297 if warn: 298 add_warning(req, warn) 299 return self._render_confirm_rename(req, page) 300 301 @with_transaction(self.env) 302 def do_rename(db): 303 page.rename(new_name, db) 304 if leave_redirection: 305 redirection_page = WikiPage(self.env, old_name) 306 redirection_page.text = _("See [wiki:%(page)s].", 307 page=new_name) 308 author = get_reporter_id(req) 309 comment = _("[wiki:'%(new_name)s@%(old_version)d' " 310 "%(old_name)s] was renamed to %(new_name)s", 311 old_name=old_name, old_version=old_version, 312 new_name=new_name) 313 redirection_page.save(author, comment, req.remote_addr, 314 None, db) 315 316 req.redirect(req.href.wiki(leave_redirection and old_name or new_name)) 317 318 319 272 320 def _do_save(self, req, page): 273 321 if page.readonly: 274 322 req.perm(page.resource).require('WIKI_ADMIN') … … class WikiModule(Component): 293 341 add_warning(req, _("Page not modified, showing latest version.")) 294 342 return self._render_view(req, page) 295 343 296 def _render_confirm (self, req, page):344 def _render_confirm_delete(self, req, page): 297 345 if page.readonly: 298 346 req.perm(page.resource).require('WIKI_ADMIN') 299 347 else: … … class WikiModule(Component): 315 363 break 316 364 data.update({'new_version': version, 'old_version': old_version, 317 365 'num_versions': num_versions}) 366 mapped = self.env.get_urlmap(page.name, reverse=True) 367 if mapped: 368 add_warning(req, _("""'%s' is the '%s' trac system page. 369 Really delete?""") % (page.name, mapped)) 318 370 self._wiki_ctxtnav(req, page) 319 371 return 'wiki_delete.html', data, None 320 372 373 def _render_confirm_rename(self, req, page): 374 if page.readonly: 375 req.perm(page.resource).require('WIKI_ADMIN') 376 else: 377 req.perm(page.resource).require('WIKI_RENAME') 378 379 data = self._page_data(req, page, 'rename') 380 mapped = self.env.get_urlmap(page.name, reverse=True) 381 if mapped: 382 add_warning(req, _("""'%s' is the '%s' trac system page. 383 Really rename?""") % (page.name, mapped)) 384 self._wiki_ctxtnav(req, page) 385 return 'wiki_rename.html', data, None 386 387 321 388 def _render_diff(self, req, page): 322 389 if not page.exists: 323 390 raise TracError(_('Version %(num)s of page "%(name)s" does not ' … … class WikiModule(Component): 512 579 conversion[3]) 513 580 514 581 data = self._page_data(req, page) 515 if page.name == 'WikiStart':582 if page.name == self.env.get_urlmap('WikiStart'): 516 583 data['title'] = '' 517 584 518 585 ws = WikiSystem(self.env) … … class WikiModule(Component): 606 673 607 674 def _wiki_ctxtnav(self, req, page): 608 675 """Add the normal wiki ctxtnav entries.""" 609 add_ctxtnav(req, _('Start Page'), req.href.wiki('WikiStart')) 610 add_ctxtnav(req, _('Index'), req.href.wiki('TitleIndex')) 676 wikistart = self.env.get_urlmap('WikiStart') 677 titleindex = self.env.get_urlmap('TitleIndex') 678 if wikistart: 679 add_ctxtnav(req, _('Start Page'), req.href.wiki(wikistart)) 680 if titleindex: 681 add_ctxtnav(req, _('Index'), req.href.wiki(titleindex)) 611 682 if page.exists: 612 683 add_ctxtnav(req, _('History'), req.href.wiki(page.name, 613 684 action='history'))
