Source code for ploneintranet.network.browser.likes

# -*- coding: utf-8 -*-
from plone import api
from plone.app.uuid.utils import uuidToCatalogBrain
from ploneintranet.layout.memoize.view import memoize
from plone.protect import PostOnly
from ploneintranet import api as piapi
from ploneintranet.core import ploneintranetCoreMessageFactory as _
from ploneintranet.network.interfaces import INetworkTool
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.component import getUtility
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse

import uuid


[docs]class NotAllowed(Exception): pass
[docs]class ToggleLike(BrowserView): """The view 'toggle_like' callable on a normal context. """ index = ViewPageTemplateFile("templates/toggle_like.pt") def __init__(self, context, request): self.context = context # the item being liked self.request = request self.util = getUtility(INetworkTool) self.item_id = api.content.get_uuid(self.context) self.like_type = "content" @property @memoize def likerids(self): """ Wrapper to avoid memoization in subclass where that is invalid. """ return self.unmemoized_likerids @property def unmemoized_likerids(self): """ The id of the people that like this content """ return self.util.get_likers(self.like_type, item_id=self.item_id) @property @memoize def likers(self): """ Wrapper to avoid memoization in subclass where that is invalid. """ return self.unmemoized_likers @property def unmemoized_likers(self): """ The id of the people that like this content If it includes the current user, return Myself as the first element """ likers = [] userid = api.user.get_current().id include_myself = False for likerid in self.likerids: if likerid == userid: include_myself = True else: liker = piapi.userprofile.get(likerid) if liker: likers.append(liker.fullname) else: likers.append(likerid) likers.sort() if include_myself: likers.insert(0, self.context.translate(_(u"Myself"))) if not likers: return return _( "liked_by", default=u"Liked by: ${likers}", mapping={"likers": u", ".join(likers)}, )
[docs] def total_likes(self): return len(self.likerids)
def __call__(self): """ """ if not self.validate_id(self.item_id): return "No valid item-id: %s" % self.item_id self.is_liked = self.util.is_liked(self.like_type, item_id=self.item_id) # toggle like only if the button is clicked if "like_button" in self.request: self.handle_toggle() if self.is_liked: self.verb = self.context.translate(_(u"Unlike")) else: self.verb = self.context.translate(_(u"Like")) self.unique_id = uuid.uuid4().hex return self.index()
[docs] def action(self): return "%s/@@toggle_like" % self.context.absolute_url()
[docs] def handle_toggle(self): """ Perform the actual like/unlike action. Since this does a db write it cannot be called with a GET. """ PostOnly(self.request) if not self.is_liked: self.util.like(self.like_type, self.item_id) else: self.util.unlike(self.like_type, self.item_id) self.is_liked = not self.is_liked
[docs] def validate_id(self, item_id): """Check if item_id is a valid UUID""" if uuidToCatalogBrain(item_id) is not None: return True
[docs]@implementer(IPublishTraverse) class ToggleLikeStatusUpdate(ToggleLike): """The special view 'toggle_like' callable on the navroot. This works around the limitation that you cannot traverse to a StatusUpdate. Instead of calling statusupdate/@@like we call portal/@@like/statusid It uses publishTraverse to allow passing the id of an object as a path: /@@toggle_like/1453656 Note that one cannot use normal memoization on methods on this view: it's context is always the navroot, so it will memoize improperly across statusupdates. """ index = ViewPageTemplateFile("templates/toggle_like.pt") def __init__(self, context, request): """Need to override __init__ to not fetch self.item_id from context""" self.context = context # INavigationRoot self.request = request self.util = getUtility(INetworkTool) self.like_type = "update" @property def likerids(self): return self.unmemoized_likerids @property def likers(self): return self.unmemoized_likers
[docs] def publishTraverse(self, request, name): """Extract self.item_id from URL /@@toggle_like/123456""" self.item_id = str(name) return self
def __call__(self): """Because self.item_id is set via publishTraverse we need an extra check""" if not getattr(self, "item_id", False): raise KeyError( _("No item id given in sub-path. " "Use .../@@toggle_like/123456") ) return super(ToggleLikeStatusUpdate, self).__call__()
[docs] def action(self): portal_url = api.portal.get().absolute_url() return "/".join((portal_url, "@@toggle_like_statusupdate", self.item_id))
[docs] def validate_id(self, item_id): """Check if the item_id is the id of a StatusUpdate""" if item_id.isdigit(): container = piapi.microblog.get_microblog() if container and int(item_id) in container._status_mapping: return True