/
model.py
171 lines (149 loc) · 6.13 KB
/
model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# -*- coding: utf-8 -*-
#
# Copyright (C) 2003-2009 Edgewall Software
# Copyright (C) 2003-2005 Jonas Borgström <jonas@edgewall.com>
# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.org/wiki/TracLicense.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/log/.
#
# Author: Jonas Borgström <jonas@edgewall.com>
# Christopher Lenz <cmlenz@gmx.de>
import time
from datetime import datetime
from trac.core import *
from trac.resource import Resource
from trac.util.datefmt import utc, to_timestamp
from trac.util.translation import _
from trac.wiki.api import WikiSystem
class WikiPage(object):
"""Represents a wiki page (new or existing)."""
realm = 'wiki'
def __init__(self, env, name=None, version=None, db=None):
self.env = env
if isinstance(name, Resource):
self.resource = name
name = self.resource.id
else:
self.resource = Resource('wiki', name, version)
self.name = name
if name:
self._fetch(name, version, db)
else:
self.version = 0
self.text = ''
self.readonly = 0
self.old_text = self.text
self.old_readonly = self.readonly
def _fetch(self, name, version=None, db=None):
if not db:
db = self.env.get_db_cnx()
cursor = db.cursor()
if version:
cursor.execute("SELECT version,time,author,text,comment,readonly "
"FROM wiki "
"WHERE name=%s AND version=%s",
(name, int(version)))
else:
cursor.execute("SELECT version,time,author,text,comment,readonly "
"FROM wiki "
"WHERE name=%s ORDER BY version DESC LIMIT 1",
(name,))
row = cursor.fetchone()
if row:
version,time,author,text,comment,readonly = row
self.version = int(version)
self.author = author
self.time = datetime.fromtimestamp(time, utc)
self.text = text
self.comment = comment
self.readonly = readonly and int(readonly) or 0
else:
self.version = 0
self.text = self.comment = self.author = ''
self.time = None
self.readonly = 0
exists = property(fget=lambda self: self.version > 0)
def delete(self, version=None, db=None):
assert self.exists, 'Cannot delete non-existent page'
if not db:
db = self.env.get_db_cnx()
handle_ta = True
else:
handle_ta = False
cursor = db.cursor()
if version is None:
# Delete a wiki page completely
cursor.execute("DELETE FROM wiki WHERE name=%s", (self.name,))
self.env.log.info('Deleted page %s' % self.name)
else:
# Delete only a specific page version
cursor.execute("DELETE FROM wiki WHERE name=%s and version=%s",
(self.name, version))
self.env.log.info('Deleted version %d of page %s'
% (version, self.name))
if version is None or version == self.version:
self._fetch(self.name, None, db)
if not self.exists:
from trac.attachment import Attachment
# Delete orphaned attachments
Attachment.delete_all(self.env, 'wiki', self.name, db)
if handle_ta:
db.commit()
# Let change listeners know about the deletion
if not self.exists:
for listener in WikiSystem(self.env).change_listeners:
listener.wiki_page_deleted(self)
else:
for listener in WikiSystem(self.env).change_listeners:
if hasattr(listener, 'wiki_page_version_deleted'):
listener.wiki_page_version_deleted(self)
def save(self, author, comment, remote_addr, t=None, db=None):
if not db:
db = self.env.get_db_cnx()
handle_ta = True
else:
handle_ta = False
if t is None:
t = datetime.now(utc)
if self.text != self.old_text:
cursor = db.cursor()
cursor.execute("INSERT INTO wiki (name,version,time,author,ipnr,"
"text,comment,readonly) VALUES (%s,%s,%s,%s,%s,%s,"
"%s,%s)", (self.name, self.version + 1,
to_timestamp(t), author, remote_addr,
self.text, comment, self.readonly))
self.version += 1
self.resource = self.resource(version=self.version)
elif self.readonly != self.old_readonly:
cursor = db.cursor()
cursor.execute("UPDATE wiki SET readonly=%s WHERE name=%s",
(self.readonly, self.name))
else:
raise TracError(_('Page not modified'))
if handle_ta:
db.commit()
for listener in WikiSystem(self.env).change_listeners:
if self.version == 1:
listener.wiki_page_added(self)
else:
listener.wiki_page_changed(self, self.version, t, comment,
author, remote_addr)
self.old_readonly = self.readonly
self.old_text = self.text
def get_history(self, db=None):
if not db:
db = self.env.get_db_cnx()
cursor = db.cursor()
cursor.execute("SELECT version,time,author,comment,ipnr FROM wiki "
"WHERE name=%s AND version<=%s "
"ORDER BY version DESC", (self.name, self.version))
for version,ts,author,comment,ipnr in cursor:
time = datetime.fromtimestamp(ts, utc)
yield version,time,author,comment,ipnr