]> git.ipfire.org Git - ipfire.org.git/blobdiff - webapp/backend/planet.py
Massive web site update
[ipfire.org.git] / webapp / backend / planet.py
index 0c7565684e6f77a2330f18e95ecac8b89a162c57..7f69b51c526396ecd00eb80781692149f0ea87e2 100644 (file)
@@ -13,6 +13,9 @@ class PlanetEntry(Object):
 
                self.data = data
 
+       def __cmp__(self, other):
+               return cmp(self.published, other.published)
+
        @property
        def id(self):
                return self.data.id
@@ -95,10 +98,10 @@ class PlanetEntry(Object):
 
        @property
        def author(self):
-               if not hasattr(self, "__author"):
-                       self.__author = self.accounts.search(self.data.author_id)
+               if not hasattr(self, "_author"):
+                       self._author = self.accounts.get_by_uid(self.data.author_id)
 
-               return self.__author
+               return self._author
 
        def set_status(self, status):
                if self.status == status:
@@ -115,30 +118,22 @@ class PlanetEntry(Object):
        def is_published(self):
                return self.status == "published"
 
-       # Tags
-
-       def get_tags(self):
-               if not hasattr(self, "__tags"):
-                       res = self.db.query("SELECT tag FROM planet_tags \
-                               WHERE post_id = %s ORDER BY tag", self.id)
-                       self.__tags = []
-                       for row in res:
-                               self.__tags.append(row.tag)
-
-               return self.__tags
+       def count_view(self, referer=None, location=None):
+               self.db.execute("INSERT INTO planet_views(post_id, referer, location) \
+                       VALUES(%s, %s, %s)", self.id, referer, location)
 
-       def set_tags(self, tags):
-               # Delete all existing tags.
-               self.db.execute("DELETE FROM planet_tags WHERE post_id = %s", self.id)
+               if hasattr(self, "_views"):
+                       self._views += 1
 
-               self.db.executemany("INSERT INTO planet_tags(post_id, tag) VALUES(%s, %s)",
-                       ((self.id, tag) for tag in tags))
+       @property
+       def views(self):
+               if not hasattr(self, "_views"):
+                       res = self.db.get("SELECT COUNT(*) AS views FROM planet_views \
+                               WHERE post_id = %s", self.id)
 
-               # Update cache.
-               self.__tags = tags
-               self.__tags.sort()
+                       self._views = res.views
 
-       tags = property(get_tags, set_tags)
+               return self._views
 
 
 class Planet(Object):
@@ -180,6 +175,9 @@ class Planet(Object):
                        clauses.append("status = %s")
                        args.append(status)
 
+                       if status == "published":
+                               clauses.append("published <= NOW()")
+
                if author_id:
                        clauses.append("author_id = %s")
                        args.append(author_id)
@@ -215,6 +213,17 @@ class Planet(Object):
 
                return [PlanetEntry(self.backend, e) for e in entries]
 
+       def get_hot_entries(self, days=30, limit=8):
+               entries = self.db.query("WITH hottest AS (SELECT post_id, COUNT(post_id) AS count \
+                       FROM planet_views WHERE \"when\" >= NOW() - INTERVAL '%s days' \
+                       GROUP BY post_id ORDER BY count DESC) SELECT * FROM planet \
+                       LEFT JOIN hottest ON planet.id = hottest.post_id \
+                       WHERE hottest.count IS NOT NULL \
+                       ORDER BY hottest.count DESC LIMIT %s",
+                       days, limit)
+
+               return [PlanetEntry(self.backend, e) for e in entries]
+
        def render(self, text, limit=0):
                if limit and len(text) >= limit:
                        text = text[:limit] + "..."
@@ -237,7 +246,7 @@ class Planet(Object):
 
                return slug
 
-       def create(self, title, markdown, author, status="published", tags=None, published=None):
+       def create(self, title, markdown, author, status="published", published=None):
                slug = self._generate_slug(title)
                markup = self.render(markdown)
 
@@ -245,15 +254,11 @@ class Planet(Object):
                        published = datetime.datetime.utcnow()
 
                id = self.db.execute("INSERT INTO planet(author_id, slug, title, status, \
-                       markdown, markup, published) VALUES(%s, %s, %s, %s, %s, %s, %s)",
+                       markdown, markup, published) VALUES(%s, %s, %s, %s, %s, %s, %s) RETURNING id",
                        author.uid, slug, title, status, markdown, markup, published)
 
-               entry = self.get_entry_by_id(id)
-
-               if tags:
-                       entry.tags = tags
-
-               return entry
+               if id:
+                       return self.get_entry_by_id(id)
 
        def update_entry(self, entry):
                self.db.execute("UPDATE planet SET title = %s, markdown = %s WHERE id = %s",
@@ -268,33 +273,14 @@ class Planet(Object):
                return id
 
        def search(self, what):
-               # Split tags.
-               tags = what.split()
-
-               query = "SELECT planet.* FROM planet INNER JOIN ( \
-                               SELECT post_id FROM planet_tags \
-                               INNER JOIN planet ON planet_tags.post_id = planet.id \
-                               WHERE %s GROUP BY post_id HAVING COUNT(post_id) = %%s \
-                       ) pt ON planet.id = pt.post_id ORDER BY published DESC"
-
-               args = (tags, len(tags))
-
-               clauses, args = [], tags
-               for tag in tags:
-                       clauses.append("planet_tags.tag = %s")
-               args.append(len(tags))
-
-               entries = self.db.query(query % " OR ".join(clauses), *args)
-               return [PlanetEntry(self.backend, e) for e in entries]
-
-       def search_autocomplete(self, what):
-               tags = what.split()
-               last_tag = tags.pop()
-
-               res = self.db.query("SELECT tag, COUNT(tag) AS count FROM planet_tags \
-                       WHERE tag LIKE %s GROUP BY tag ORDER BY count DESC", "%s%%" % last_tag)
-
-               if tags:
-                       return ["%s %s" % (" ".join(tags), row.tag) for row in res]
-
-               return [row.tag for row in res]
+               res = self.db.query("WITH \
+                       q      AS (SELECT plainto_tsquery(%s, %s) AS query), \
+                       ranked AS (SELECT id, query, ts_rank_cd(to_tsvector(%s, markdown), query) AS rank \
+                               FROM planet, q WHERE markdown @@ query ORDER BY rank DESC) \
+                       SELECT *, ts_headline(markup, ranked.query, 'MinWords=100, MaxWords=110') AS markup FROM planet \
+                               JOIN ranked ON planet.id = ranked.id \
+                               WHERE status = %s AND published IS NOT NULL AND published <= NOW() \
+                               ORDER BY ranked DESC LIMIT 25",
+                       "english", what, "english", "published")
+
+               return [PlanetEntry(self.backend, e) for e in res]