]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - webapp/backend/planet.py
planet: Add yearly summary.
[people/shoehn/ipfire.org.git] / webapp / backend / planet.py
1 #!/usr/bin/python
2
3 import re
4 import textile
5 import tornado.database
6 import unicodedata
7
8 from accounts import Accounts
9 from databases import Databases
10
11 from misc import Singleton
12
13 class PlanetEntry(object):
14 def __init__(self, entry=None):
15 if entry:
16 self.__entry = entry
17 else:
18 self.__entry = tornado.database.Row({
19 "id" : None,
20 "title" : "",
21 "markdown" : "",
22 })
23
24 def set(self, key, val):
25 self.__entry[key] = val
26
27 @property
28 def planet(self):
29 return Planet()
30
31 @property
32 def id(self):
33 return self.__entry.id
34
35 @property
36 def slug(self):
37 return self.__entry.slug
38
39 @property
40 def title(self):
41 return self.__entry.title
42
43 @property
44 def published(self):
45 return self.__entry.published
46
47 @property
48 def year(self):
49 return self.published.year
50
51 @property
52 def month(self):
53 return self.published.month
54
55 @property
56 def updated(self):
57 return self.__entry.updated
58
59 @property
60 def markdown(self):
61 return self.__entry.markdown
62
63 @property
64 def abstract(self):
65 return self.render(self.markdown, 400)
66
67 def render(self, text, limit=0):
68 return self.planet.render(text, limit)
69
70 @property
71 def text(self):
72 return self.render(self.markdown)
73
74 @property
75 def author(self):
76 return Accounts().search(self.__entry.author_id)
77
78
79 class Planet(object):
80 __metaclass__ = Singleton
81
82 @property
83 def db(self):
84 return Databases().webapp
85
86 def get_authors(self):
87 authors = []
88 for author in self.db.query("SELECT DISTINCT author_id FROM planet"):
89 author = Accounts().search(author.author_id)
90 if author:
91 authors.append(author)
92
93 return sorted(authors)
94
95 def get_years(self):
96 res = self.db.query("SELECT DISTINCT YEAR(published) AS year \
97 FROM planet ORDER BY year DESC")
98
99 return [row.year for row in res]
100
101 def get_entry_by_slug(self, slug):
102 entry = self.db.get("SELECT * FROM planet WHERE slug = %s", slug)
103 if entry:
104 return PlanetEntry(entry)
105
106 def get_entry_by_id(self, id):
107 entry = self.db.get("SELECT * FROM planet WHERE id = %s", id)
108 if entry:
109 return PlanetEntry(entry)
110
111 def _limit_and_offset_query(self, limit=None, offset=None):
112 query = " "
113
114 if limit:
115 if offset:
116 query += "LIMIT %d,%d" % (offset, limit)
117 else:
118 query += "LIMIT %d" % limit
119
120 return query
121
122 def get_entries(self, limit=3, offset=None):
123 query = "SELECT * FROM planet WHERE acknowledged='Y' ORDER BY published DESC"
124
125 # Respect limit and offset
126 query += self._limit_and_offset_query(limit=limit, offset=offset)
127
128 entries = []
129 for entry in self.db.query(query):
130 entries.append(PlanetEntry(entry))
131
132 return entries
133
134 def get_entries_by_author(self, author_id, limit=None, offset=None):
135 query = "SELECT * FROM planet WHERE author_id = '%s'" % author_id
136 query += " AND acknowledged='Y' ORDER BY published DESC"
137
138 # Respect limit and offset
139 query += self._limit_and_offset_query(limit=limit, offset=offset)
140
141 entries = self.db.query(query)
142
143 return [PlanetEntry(e) for e in entries]
144
145 def get_entries_by_year(self, year):
146 entries = self.db.query("SELECT * FROM planet \
147 WHERE YEAR(published) = %s ORDER BY published DESC", year)
148
149 return [PlanetEntry(e) for e in entries]
150
151 def render(self, text, limit=0):
152 if limit and len(text) >= limit:
153 text = text[:limit] + "..."
154 return textile.textile(text)
155
156 def _generate_slug(self, title):
157 slug = unicodedata.normalize("NFKD", title).encode("ascii", "ignore")
158 slug = re.sub(r"[^\w]+", " ", slug)
159 slug = "-".join(slug.lower().strip().split())
160
161 if not slug:
162 slug = "entry"
163
164 while True:
165 e = self.db.get("SELECT * FROM planet WHERE slug = %s", slug)
166 if not e:
167 break
168 slug += "-"
169
170 return slug
171
172 def update_entry(self, entry):
173 self.db.execute("UPDATE planet SET title = %s, markdown = %s WHERE id = %s",
174 entry.title, entry.markdown, entry.id)
175
176 def save_entry(self, entry):
177 slug = self._generate_slug(entry.title)
178
179 self.db.execute("INSERT INTO planet(author_id, title, slug, markdown, published) "
180 "VALUES(%s, %s, %s, %s, UTC_TIMESTAMP())", entry.author.uid, entry.title,
181 slug, entry.markdown)
182
183 def search(self, what):
184 entries = self.db.query("SELECT *, MATCH(markdown, title) AGAINST(%s) AS score \
185 FROM planet WHERE MATCH(markdown, title) AGAINST(%s) ORDER BY score DESC", what, what)
186
187 return [PlanetEntry(e) for e in entries]