Completed
Pull Request — master (#345)
by
unknown
29s
created

IsFollowing   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 9
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 10
c 0
b 0
f 0
wmc 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A render_result() 0 6 1
1
from django.contrib.contenttypes.models import ContentType
2
from django.core.urlresolvers import reverse
3
from django.template import Variable, Library, Node, TemplateSyntaxError
4
from django.template.loader import render_to_string
5
6
from actstream.models import Follow, Action
7
8
9
register = Library()
10
11
12
class DisplayActivityFollowUrl(Node):
13
    def __init__(self, actor, actor_only=True, flag=''):
14
        self.actor = Variable(actor)
15
        self.actor_only = actor_only
16
        self.flag = flag
17
18
    def render(self, context):
19
        actor_instance = self.actor.resolve(context)
20
        content_type = ContentType.objects.get_for_model(actor_instance).pk
21
22
        kwargs = {
23
            'content_type_id': content_type,
24
            'object_id': actor_instance.pk
25
        }
26
27
        if self.flag:
28
            kwargs['flag'] = self.flag
29
30
        if Follow.objects.is_following(context.get('user'), actor_instance, flag=self.flag):
31
            return reverse('actstream_unfollow', kwargs=kwargs)
32
        if self.actor_only:
33
            return reverse('actstream_follow', kwargs=kwargs)
34
        return reverse('actstream_follow_all', kwargs=kwargs)
35
36
37
class DisplayActivityActorUrl(Node):
38
    def __init__(self, actor):
39
        self.actor = Variable(actor)
40
41
    def render(self, context):
42
        actor_instance = self.actor.resolve(context)
43
        content_type = ContentType.objects.get_for_model(actor_instance).pk
44
        return reverse('actstream_actor', kwargs={
45
            'content_type_id': content_type, 'object_id': actor_instance.pk})
46
47
48
class AsNode(Node):
49
    """
50
    Base template Node class for template tags that takes a predefined number
51
    of arguments, ending in an optional 'as var' section.
52
    """
53
    args_count = 1
54
55
    @classmethod
56
    def handle_token(cls, parser, token):
57
        """
58
        Class method to parse and return a Node.
59
        """
60
        tag_error = "Accepted formats {%% %(tagname)s %(args)s %%} or " \
61
                    "{%% %(tagname)s %(args)s as [var] %%}"
62
        bits = token.split_contents()
63
        args_count = len(bits) - 1
64
        if args_count >= 2 and bits[-2] == 'as':
65
            as_var = bits[-1]
66
            args_count -= 2
67
        else:
68
            as_var = None
69
        if args_count != cls.args_count:
70
            arg_list = ' '.join(['[arg]' * cls.args_count])
71
            raise TemplateSyntaxError(tag_error % {'tagname': bits[0],
72
                                                   'args': arg_list})
73
        args = [parser.compile_filter(tkn)
74
                for tkn in bits[1:args_count + 1]]
75
        return cls(args, varname=as_var)
76
77
    def __init__(self, args, varname=None):
78
        self.args = args
79
        self.varname = varname
80
81
    def render(self, context):
82
        result = self.render_result(context)
83
        if self.varname is not None:
84
            context[self.varname] = result
85
            return ''
86
        return result
87
88
    def render_result(self, context):
89
        raise NotImplementedError("Must be implemented by a subclass")
90
91
92
class DisplayAction(AsNode):
93
94
    def render_result(self, context):
95
        action_instance = context['action'] = self.args[0].resolve(context)
96
        templates = [
97
            'actstream/%s/action.html' % action_instance.verb.replace(' ', '_'),
98
            'actstream/action.html',
99
        ]
100
        return render_to_string(templates, {'action': action_instance})
101
102
103
def display_action(parser, token):
104
    """
105
    Renders the template for the action description
106
107
    ::
108
109
        {% display_action action %}
110
    """
111
    return DisplayAction.handle_token(parser, token)
112
113
114
def is_following(user, actor):
115
    """
116
    Returns true if the given user is following the actor
117
118
    ::
119
120
        {% if request.user|is_following:another_user %}
121
            You are already following {{ another_user }}
122
        {% endif %}
123
    """
124
    return Follow.objects.is_following(user, actor)
125
126
127
class IsFollowing(AsNode):
128
    args_count = 3
129
130
    def render_result(self, context):
131
        user= self.args[0].resolve(context)
132
        actor = self.args[1].resolve(context)
133
        flag = self.args[2].resolve(context)
134
135
        return Follow.objects.is_following(user, actor, flag=flag)
136
137
138
def is_following_tag(parser, token):
139
    """
140
    Returns true if the given user is following the actor marked by a flag, such as 'liking', 'watching' etc..
141
    You can also save the returned value to a template variable by as syntax.
142
    If you don't want to specify a flag, pass an empty string or use `is_following` template filter.
143
144
    ::
145
146
        {% is_following user group "liking" %}
147
        {% is_following user group "liking" as is_liking %}
148
        {% is_following user group "" as is_following %}
149
    """
150
    return IsFollowing.handle_token(parser, token)
151
152
153 View Code Duplication
def follow_url(parser, token):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
154
    """
155
    Renders the URL of the follow view for a particular actor instance
156
157
    ::
158
159
        <a href="{% follow_url other_user %}">
160
            {% if request.user|is_following:other_user %}
161
                stop following
162
            {% else %}
163
                follow
164
            {% endif %}
165
        </a>
166
167
        <a href="{% follow_url other_user 'watching' %}">
168
            {% is_following user group "watching" as is_watching %}
169
            {% if is_watching %}
170
                stop watching
171
            {% else %}
172
                watch
173
            {% endif %}
174
        </a>
175
    """
176
    bits = token.split_contents()
177
178
    if len(bits) > 3:
179
        raise TemplateSyntaxError("Accepted format {% follow_url [instance] %} or {% follow_url [instance] [flag] %}")
180
    elif len(bits) == 2:
181
        return DisplayActivityFollowUrl(bits[1])
182
    else:
183
        flag = bits[2][1:-1]
184
        return DisplayActivityFollowUrl(bits[1], flag=flag)
185
186
187 View Code Duplication
def follow_all_url(parser, token):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
188
    """
189
    Renders the URL to follow an object as both actor and target
190
191
    ::
192
193
        <a href="{% follow_all_url other_user %}">
194
            {% if request.user|is_following:other_user %}
195
                stop following
196
            {% else %}
197
                follow
198
            {% endif %}
199
        </a>
200
201
        <a href="{% follow_all_url other_user 'watching' %}">
202
            {% is_following user group "watching" as is_watching %}
203
            {% if is_watching %}
204
                stop watching
205
            {% else %}
206
                watch
207
            {% endif %}
208
        </a>
209
    """
210
    bits = token.split_contents()
211
    if len(bits) > 3:
212
        raise TemplateSyntaxError(
213
            "Accepted format {% follow_all_url [instance] %} or {% follow_url [instance] [flag] %}"
214
        )
215
    elif len(bits) == 2:
216
        return DisplayActivityFollowUrl(bits[1], actor_only=False)
217
    else:
218
        flag = bits[2][1:-1]
219
        return DisplayActivityFollowUrl(bits[1], actor_only=False, flag=flag)
220
221
222
def actor_url(parser, token):
223
    """
224
    Renders the URL for a particular actor instance
225
226
    ::
227
228
        <a href="{% actor_url request.user %}">View your actions</a>
229
        <a href="{% actor_url another_user %}">{{ another_user }}'s actions</a>
230
231
    """
232
    bits = token.split_contents()
233
    if len(bits) != 2:
234
        raise TemplateSyntaxError("Accepted format "
235
                                  "{% actor_url [actor_instance] %}")
236
    else:
237
        return DisplayActivityActorUrl(*bits[1:])
238
239
240
def activity_stream(context, stream_type, *args, **kwargs):
241
    """
242
    Renders an activity stream as a list into the template's context.
243
    Streams loaded by stream_type can be the default ones (eg user, actor, etc.) or a user defined stream.
244
    Extra args/kwargs are passed into the stream call.
245
246
    ::
247
248
        {% activity_stream 'actor' user %}
249
        {% for action in stream %}
250
            {% display_action action %}
251
        {% endfor %}
252
    """
253
    if stream_type == 'model':
254
        stream_type = 'model_actions'
255
    if not hasattr(Action.objects, stream_type):
256
        raise TemplateSyntaxError('Action manager has no attribute: %s' % stream_type)
257
    ctxvar = kwargs.pop('as', 'stream')
258
    context[ctxvar] = getattr(Action.objects, stream_type)(*args, **kwargs)
259
    return ''
260
261
262
register.filter(activity_stream)
263
register.filter(is_following)
264
register.tag(name='is_following', compile_function=is_following_tag)
265
register.tag(display_action)
266
register.tag(follow_url)
267
register.tag(follow_all_url)
268
register.tag(actor_url)
269
register.simple_tag(takes_context=True)(activity_stream)
270