Personal wiki notebook (not under development)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Note.py 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import re
  2. from Persistent import Persistent, quote
  3. from controller.Html_nuker import Html_nuker
  4. class Note( Persistent ):
  5. """
  6. An single textual wiki note.
  7. """
  8. TITLE_PATTERN = re.compile( u"<h3>(.*?)</h3>", flags = re.IGNORECASE )
  9. def __init__( self, object_id, revision = None, title = None, contents = None, notebook_id = None,
  10. startup = None, deleted_from_id = None, rank = None, user_id = None,
  11. username = None, creation = None, summary = None ):
  12. """
  13. Create a new note with the given id and contents.
  14. @type object_id: unicode
  15. @param object_id: id of the note
  16. @type revision: datetime or NoneType
  17. @param revision: revision timestamp of the object (optional, defaults to now)
  18. @type title: unicode or NoneType
  19. @param title: textual title of the note (optional, defaults to derived from contents)
  20. @type contents: unicode or NoneType
  21. @param contents: HTML contents of the note (optional)
  22. @type notebook_id: unicode or NoneType
  23. @param notebook_id: id of notebook containing this note (optional)
  24. @type startup: bool or NoneType
  25. @param startup: whether this note should be displayed upon startup (optional, defaults to False)
  26. @type deleted_from_id: unicode or NoneType
  27. @param deleted_from_id: id of the notebook that this note was deleted from (optional)
  28. @type rank: float or NoneType
  29. @param rank: indicates numeric ordering of this note in relation to other startup notes
  30. @type user_id: unicode or NoneType
  31. @param user_id: id of the user who most recently updated this note object (optional)
  32. @type username: unicode or NoneType
  33. @param username: username of the user who most recently updated this note object (optional)
  34. @type creation: datetime or NoneType
  35. @param creation: creation timestamp of the object (optional, defaults to None)
  36. @type summary: unicode or NoneType
  37. @param summary: textual summary of the note's contents (optional, defaults to None)
  38. @rtype: Note
  39. @return: newly constructed note
  40. """
  41. Persistent.__init__( self, object_id, revision )
  42. self.__title = title
  43. self.__contents = contents
  44. self.__summary = summary
  45. self.__notebook_id = notebook_id
  46. self.__startup = startup or False
  47. self.__deleted_from_id = deleted_from_id
  48. self.__rank = rank
  49. self.__user_id = user_id
  50. self.__username = username
  51. self.__creation = creation
  52. @staticmethod
  53. def create( object_id, contents = None, notebook_id = None, startup = None, rank = None,
  54. user_id = None, username = None, creation = None, summary = None ):
  55. """
  56. Convenience constructor for creating a new note.
  57. @type object_id: unicode
  58. @param object_id: id of the note
  59. @type contents: unicode or NoneType
  60. @param contents: HTML contents of the note (optional)
  61. @type notebook_id: unicode or NoneType
  62. @param notebook_id: id of notebook containing this note (optional)
  63. @type startup: bool or NoneType
  64. @param startup: whether this note should be displayed upon startup (optional, defaults to False)
  65. @type rank: float or NoneType
  66. @param rank: indicates numeric ordering of this note in relation to other startup notes
  67. @type user_id: unicode or NoneType
  68. @param user_id: id of the user who most recently updated this note object (optional)
  69. @type username: unicode or NoneType
  70. @param username: username of the user who most recently updated this note object (optional)
  71. @type creation: datetime or NoneType
  72. @param creation: creation timestamp of the object (optional, defaults to None)
  73. @type summary: unicode or NoneType
  74. @param summary: textual summary of the note's contents (optional, defaults to None)
  75. @rtype: Note
  76. @return: newly constructed note
  77. """
  78. note = Note(
  79. object_id, notebook_id = notebook_id, startup = startup, rank = rank, user_id = user_id,
  80. username = username, creation = creation, summary = summary
  81. )
  82. note.contents = contents
  83. return note
  84. def __set_contents( self, contents ):
  85. self.update_revision()
  86. self.__contents = contents
  87. if contents is None:
  88. self.__title = None
  89. return
  90. # parse title out of the beginning of the contents
  91. result = Note.TITLE_PATTERN.search( contents )
  92. if result:
  93. self.__title = result.groups()[ 0 ]
  94. self.__title = Html_nuker( allow_refs = True ).nuke( self.__title )
  95. else:
  96. self.__title = None
  97. def replace_contents( self, contents ):
  98. self.__contents = contents
  99. def __set_summary( self, summary ):
  100. self.__summary = summary
  101. def __set_notebook_id( self, notebook_id ):
  102. self.__notebook_id = notebook_id
  103. self.update_revision()
  104. def __set_startup( self, startup ):
  105. self.__startup = startup
  106. self.update_revision()
  107. def __set_deleted_from_id( self, deleted_from_id ):
  108. self.__deleted_from_id = deleted_from_id
  109. self.update_revision()
  110. def __set_rank( self, rank ):
  111. self.__rank = rank
  112. self.update_revision()
  113. def __set_user_id( self, user_id ):
  114. self.__user_id = user_id
  115. self.update_revision()
  116. @staticmethod
  117. def sql_load( object_id, revision = None ):
  118. if revision:
  119. return "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note where id = %s and revision = %s;" % ( quote( object_id ), quote( revision ) )
  120. return "select id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id from note_current where id = %s;" % quote( object_id )
  121. @staticmethod
  122. def sql_id_exists( object_id, revision = None ):
  123. if revision:
  124. return "select id from note where id = %s and revision = %s;" % ( quote( object_id ), quote( revision ) )
  125. return "select id from note_current where id = %s;" % quote( object_id )
  126. def sql_exists( self ):
  127. return Note.sql_id_exists( self.object_id )
  128. def sql_create( self ):
  129. rank = self.__rank
  130. if rank is None:
  131. rank = quote( None )
  132. # this relies on a database trigger to copy the new row into the note table
  133. return \
  134. "insert into note_current ( id, revision, title, contents, notebook_id, startup, deleted_from_id, rank, user_id ) " + \
  135. "values ( %s, %s, %s, %s, %s, %s, %s, %s, %s );" % \
  136. ( quote( self.object_id ), quote( self.revision ), quote( self.__title ),
  137. quote( self.__contents ), quote( self.__notebook_id ), quote( self.__startup and 't' or 'f' ),
  138. quote( self.__deleted_from_id ), rank, quote( self.user_id ) )
  139. def sql_update( self ):
  140. rank = self.__rank
  141. if rank is None:
  142. rank = quote( None )
  143. # this relies on a database trigger to copy the updated row into the note table
  144. return \
  145. """
  146. update note_current set id = %s, revision = %s, title = %s, contents = %s, notebook_id = %s,
  147. startup = %s, deleted_from_id = %s, rank = %s, user_id = %s where id = %s;
  148. """ % \
  149. ( quote( self.object_id ), quote( self.revision ), quote( self.__title ),
  150. quote( self.__contents ), quote( self.__notebook_id ), quote( self.__startup and 't' or 'f' ),
  151. quote( self.__deleted_from_id ), rank, quote( self.user_id ), quote( self.object_id ) )
  152. def sql_load_revisions( self ):
  153. return """ \
  154. select
  155. note.revision, luminotes_user_current.id, username
  156. from
  157. note left outer join luminotes_user_current
  158. on
  159. ( note.user_id = luminotes_user_current.id )
  160. where
  161. note.id = %s order by note.revision;
  162. """ % quote( self.object_id )
  163. def to_dict( self ):
  164. d = Persistent.to_dict( self )
  165. d.update( dict(
  166. contents = self.__contents,
  167. summary = self.__summary,
  168. notebook_id = self.__notebook_id,
  169. title = self.__title,
  170. deleted_from_id = self.__deleted_from_id,
  171. user_id = self.__user_id,
  172. username = self.__username,
  173. creation = self.__creation,
  174. ) )
  175. return d
  176. title = property( lambda self: self.__title )
  177. contents = property( lambda self: self.__contents, __set_contents )
  178. summary = property( lambda self: self.__summary, __set_summary )
  179. notebook_id = property( lambda self: self.__notebook_id, __set_notebook_id )
  180. startup = property( lambda self: self.__startup, __set_startup )
  181. deleted_from_id = property( lambda self: self.__deleted_from_id, __set_deleted_from_id )
  182. rank = property( lambda self: self.__rank, __set_rank )
  183. user_id = property( lambda self: self.__user_id, __set_user_id )
  184. username = property( lambda self: self.__username )
  185. creation = property( lambda self: self.__creation )