summaryrefslogtreecommitdiffstats
path: root/forum/search/state_manager.py
blob: 6a38a7a2d90ad520e4a9bf2a9eaa37fd7b1c77f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#search state manager object
#that lives in the session and takes care of the state
#persistece during the search session
from forum import const
import logging

ACTIVE_COMMANDS = (
    'sort', 'search', 'query',
    'reset_query', 'reset_author', 'reset_tags',
    'tags', 'scope', 'page_size', 'start_over',
    'page'
)

def some_in(what, where):
    for element in what:
        if element in where:
            return True
    return False

class SearchState(object):
    def __init__(self):
        self.scope= const.DEFAULT_POST_SCOPE
        self.query = None
        self.tags = None
        self.author = None
        self.sort = const.DEFAULT_POST_SORT_METHOD
        self.page_size = const.DEFAULT_QUESTIONS_PAGE_SIZE
        self.page = 1
        self.logged_in = False
        logging.debug('new search state initialized')

    def __str__(self):
        out = 'scope=%s\n' % self.scope
        out += 'query=%s\n' % self.query
        if self.tags:
            out += 'tags=%s\n' % ','.join(self.tags)
        out += 'author=%s\n' % self.author
        out += 'sort=%s\n' % self.sort
        out += 'page_size=%d\n' % self.page_size
        out += 'page=%d\n' % self.page
        out += 'logged_in=%s\n' % str(self.logged_in)
        return out

    def set_logged_out(self):
        if self.scope == 'favorite':
            self.scope = None
        self.logged_in = False

    def set_logged_in(self):
        self.logged_in = True

    def reset(self):
        #re-initialize, but keep login state
        is_logged_in = self.logged_in
        self.__init__()
        self.logged_in = is_logged_in

    def update_value(self, key, store):
        if key in store:
            old_value = getattr(self, key)
            new_value = store[key]
            if new_value != old_value:
                setattr(self, key, new_value)
                self.reset_page()

    def relax_stickiness(self, input, view_log):
        if view_log.get_previous(1) == 'questions':
            if not some_in(ACTIVE_COMMANDS, input):
                self.reset()
        #todo also relax if 'all' scope was clicked twice

    def update_from_user_input(self,input,raw_input = {}):
        #todo: this function will probably not 
        #fit the case of multiple parameters entered at the same tiem
        if 'start_over' in input:
            self.reset()

        if 'page' in input:
            self.page = input['page']
            #special case - on page flip no other input is accepted
            return

        if 'page_size' in input:
            self.update_value('page_size',input)
            self.reset_page()#todo may be smarter here - start with ~same q
            #same as with page - return right away
            return

        if 'scope' in input:
            if input['scope'] == 'favorite' and self.logged_in == False:
                self.reset_scope()
            else:
                self.update_value('scope',input)

        if 'tags' in input:
            if self.tags:
                old_tags = self.tags.copy()
                self.tags = self.tags.union(input['tags'])
                if self.tags != old_tags:
                    self.reset_page()
            else:
                self.tags = input['tags']

        #all resets just return
        if 'reset_tags' in input:
            if self.tags:
                self.tags = None
                self.reset_page()
            return

        #todo: handle case of deleting tags one-by-one
        if 'reset_author' in input:
            if self.author:
                self.author = None
                self.reset_page()
            return

        if 'reset_query' in input:
            self.reset_query()
            return

        self.update_value('author',input)

        if 'query' in input:
            self.update_value('query',input)
            self.sort = 'relevant'
        elif 'search' in raw_input:#a case of use nulling search query by hand
            self.reset_query()
            return

        if 'sort' in input:
            if input['sort'] == 'relevant' and self.query is None:
                self.reset_sort()
            else:
                self.update_value('sort',input)

        #todo: plug - mysql has no relevance sort
        if self.sort == 'relevant':
            self.reset_sort()

    def reset_page(self):
        self.page = 1

    def reset_query(self):
        if self.query:
            self.query = None
            self.reset_page()
            if self.sort == 'relevant':
                self.reset_sort()

    def reset_sort(self):
        self.sort = const.DEFAULT_POST_SORT_METHOD

    def reset_scope(self):
        self.scope = const.DEFAULT_POST_SCOPE