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