72 if len(ptypes) == 1: |
72 if len(ptypes) == 1: |
73 return display_name(facet._cw, facet.rtype, form=facet.role, |
73 return display_name(facet._cw, facet.rtype, form=facet.role, |
74 context=iter(ptypes).next()) |
74 context=iter(ptypes).next()) |
75 return display_name(facet._cw, facet.rtype, form=facet.role) |
75 return display_name(facet._cw, facet.rtype, form=facet.role) |
76 |
76 |
77 def filtered_variable(rqlst): |
77 def get_facet(req, facetid, select, filtered_variable): |
78 vref = rqlst.selection[0].iget_nodes(nodes.VariableRef).next() |
78 return req.vreg['facets'].object_by_id(facetid, req, select=select, |
79 return vref.variable |
79 filtered_variable=filtered_variable) |
80 |
|
81 def get_facet(req, facetid, rqlst, mainvar): |
|
82 return req.vreg['facets'].object_by_id(facetid, req, rqlst=rqlst, |
|
83 filtered_variable=mainvar) |
|
84 |
80 |
85 @deprecated('[3.13] filter_hiddens moved to cubicweb.web.views.facets with ' |
81 @deprecated('[3.13] filter_hiddens moved to cubicweb.web.views.facets with ' |
86 'slightly modified prototype') |
82 'slightly modified prototype') |
87 def filter_hiddens(w, **kwargs): |
83 def filter_hiddens(w, **kwargs): |
88 from cubicweb.web.views.facets import filter_hiddens |
84 from cubicweb.web.views.facets import filter_hiddens |
89 return filter_hiddens(w, wdgs=kwargs.pop('facets')) |
85 return filter_hiddens(w, wdgs=kwargs.pop('facets')) |
90 |
86 |
91 |
87 |
92 ## rqlst manipulation functions used by facets ################################ |
88 ## rqlst manipulation functions used by facets ################################ |
93 |
89 |
94 def prepare_facets_rqlst(rqlst, args=None): |
90 def init_facets(rset, select, mainvar=None): |
|
91 rset.req.vreg.rqlhelper.annotate(select) |
|
92 filtered_variable = get_filtered_variable(select, mainvar) |
|
93 baserql = select.as_string(kwargs=rset.args) # before call to prepare_select |
|
94 prepare_select(select, filtered_variable) |
|
95 return filtered_variable, baserql |
|
96 |
|
97 def get_filtered_variable(select, mainvar=None): |
|
98 """drop any limit/offset from select (in-place modification) and return the |
|
99 variable whose name is `mainvar` or the first variable selected in column 0 |
|
100 """ |
|
101 select.set_limit(None) |
|
102 select.set_offset(None) |
|
103 if mainvar is None: |
|
104 vref = select.selection[0].iget_nodes(nodes.VariableRef).next() |
|
105 return vref.variable |
|
106 return select.defined_vars[mainvar] |
|
107 |
|
108 def prepare_select(select, filtered_variable): |
95 """prepare a syntax tree to generate facet filters |
109 """prepare a syntax tree to generate facet filters |
96 |
110 |
97 * remove ORDERBY/GROUPBY clauses |
111 * remove ORDERBY/GROUPBY clauses |
98 * cleanup selection (remove everything) |
112 * cleanup selection (remove everything) |
99 * undefine unnecessary variables |
113 * undefine unnecessary variables |
100 * set DISTINCT |
114 * set DISTINCT |
101 * unset LIMIT/OFFSET |
115 |
102 """ |
116 Notice unset of LIMIT/OFFSET us expected to be done by a previous call to |
103 assert len(rqlst.children) == 1, 'FIXME: union not yet supported' |
117 :func:`get_filtered_variable`. |
104 select = rqlst.children[0] |
118 """ |
105 mainvar = filtered_variable(select) |
|
106 select.set_limit(None) |
|
107 select.set_offset(None) |
|
108 baserql = select.as_string(kwargs=args) |
|
109 # cleanup sort terms / group by |
119 # cleanup sort terms / group by |
110 select.remove_sort_terms() |
120 select.remove_sort_terms() |
111 select.remove_groups() |
121 select.remove_groups() |
112 # XXX remove aggregat from having |
122 # XXX remove aggregat from having |
113 # selection: only vocabulary entity |
123 # selection: only vocabulary entity |
114 for term in select.selection[:]: |
124 for term in select.selection[:]: |
115 select.remove_selected(term) |
125 select.remove_selected(term) |
116 # remove unbound variables which only have some type restriction |
126 # remove unbound variables which only have some type restriction |
117 for dvar in select.defined_vars.values(): |
127 for dvar in select.defined_vars.values(): |
118 if not (dvar is mainvar or dvar.stinfo['relations']): |
128 if not (dvar is filtered_variable or dvar.stinfo['relations']): |
119 select.undefine_variable(dvar) |
129 select.undefine_variable(dvar) |
120 # global tree config: DISTINCT, LIMIT, OFFSET |
130 # global tree config: DISTINCT, LIMIT, OFFSET |
121 select.set_distinct(True) |
131 select.set_distinct(True) |
122 return mainvar, baserql |
132 |
123 |
133 @deprecated('[3.13] use init_facets instead') |
124 |
134 def prepare_facets_rqlst(rqlst, args=None): |
125 def prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role, |
135 assert len(rqlst.children) == 1, 'FIXME: union not yet supported' |
|
136 select = rqlst.children[0] |
|
137 filtered_variable = get_filtered_variable(select) |
|
138 baserql = select.as_string(args) |
|
139 prepare_select(select, filtered_variable) |
|
140 return filtered_variable, baserql |
|
141 |
|
142 def prepare_vocabulary_select(select, filtered_variable, rtype, role, |
126 select_target_entity=True): |
143 select_target_entity=True): |
127 """prepare a syntax tree to generate a filter vocabulary rql using the given |
144 """prepare a syntax tree to generate a filter vocabulary rql using the given |
128 relation: |
145 relation: |
129 * create a variable to filter on this relation |
146 * create a variable to filter on this relation |
130 * add the relation |
147 * add the relation |
131 * add the new variable to GROUPBY clause if necessary |
148 * add the new variable to GROUPBY clause if necessary |
132 * add the new variable to the selection |
149 * add the new variable to the selection |
133 """ |
150 """ |
134 newvar = _add_rtype_relation(rqlst, mainvar, rtype, role)[0] |
151 newvar = _add_rtype_relation(select, filtered_variable, rtype, role)[0] |
135 if select_target_entity: |
152 if select_target_entity: |
136 if rqlst.groupby: |
153 if select.groupby: |
137 rqlst.add_group_var(newvar) |
154 select.add_group_var(newvar) |
138 rqlst.add_selected(newvar) |
155 select.add_selected(newvar) |
139 # add is restriction if necessary |
156 # add is restriction if necessary |
140 if mainvar.stinfo['typerel'] is None: |
157 if filtered_variable.stinfo['typerel'] is None: |
141 etypes = frozenset(sol[mainvar.name] for sol in rqlst.solutions) |
158 etypes = frozenset(sol[filtered_variable.name] for sol in select.solutions) |
142 rqlst.add_type_restriction(mainvar, etypes) |
159 select.add_type_restriction(filtered_variable, etypes) |
143 return newvar |
160 return newvar |
144 |
161 |
145 |
162 |
146 def insert_attr_select_relation(rqlst, mainvar, rtype, role, attrname, |
163 def insert_attr_select_relation(select, filtered_variable, rtype, role, attrname, |
147 sortfuncname=None, sortasc=True, |
164 sortfuncname=None, sortasc=True, |
148 select_target_entity=True): |
165 select_target_entity=True): |
149 """modify a syntax tree to : |
166 """modify a syntax tree to : |
150 * link a new variable to `mainvar` through `rtype` (where mainvar has `role`) |
167 * link a new variable to `filtered_variable` through `rtype` (where filtered_variable has `role`) |
151 * retrieve only the newly inserted variable and its `attrname` |
168 * retrieve only the newly inserted variable and its `attrname` |
152 |
169 |
153 Sorting: |
170 Sorting: |
154 * on `attrname` ascendant (`sortasc`=True) or descendant (`sortasc`=False) |
171 * on `attrname` ascendant (`sortasc`=True) or descendant (`sortasc`=False) |
155 * on `sortfuncname`(`attrname`) if `sortfuncname` is specified |
172 * on `sortfuncname`(`attrname`) if `sortfuncname` is specified |
156 * no sort if `sortasc` is None |
173 * no sort if `sortasc` is None |
157 """ |
174 """ |
158 cleanup_rqlst(rqlst, mainvar) |
175 cleanup_select(select, filtered_variable) |
159 var = prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role, |
176 var = prepare_vocabulary_select(select, filtered_variable, rtype, role, |
160 select_target_entity) |
177 select_target_entity) |
161 attrvar = rqlst.make_variable() |
178 attrvar = select.make_variable() |
162 rqlst.add_relation(var, attrname, attrvar) |
179 select.add_relation(var, attrname, attrvar) |
163 # if query is grouped, we have to add the attribute variable |
180 # if query is grouped, we have to add the attribute variable |
164 if rqlst.groupby: |
181 #if select.groupby: XXX may not occur anymore |
165 if not attrvar in rqlst.groupby: |
182 # if not attrvar in select.groupby: |
166 rqlst.add_group_var(attrvar) |
183 # select.add_group_var(attrvar) |
167 if sortasc is not None: |
184 if sortasc is not None: |
168 _set_orderby(rqlst, attrvar, sortasc, sortfuncname) |
185 _set_orderby(select, attrvar, sortasc, sortfuncname) |
169 # add attribute variable to selection |
186 # add attribute variable to selection |
170 rqlst.add_selected(attrvar) |
187 select.add_selected(attrvar) |
171 return var |
188 return var |
172 |
189 |
173 |
190 |
174 def cleanup_rqlst(rqlst, mainvar): |
191 def cleanup_select(select, filtered_variable): |
175 """cleanup tree from unnecessary restrictions: |
192 """cleanup tree from unnecessary restrictions: |
176 * attribute selection |
193 * attribute selection |
177 * optional relations linked to the main variable |
194 * optional relations linked to the main variable |
178 * mandatory relations linked to the main variable |
195 * mandatory relations linked to the main variable |
179 """ |
196 """ |
180 if rqlst.where is None: |
197 if select.where is None: |
181 return |
198 return |
182 schema = rqlst.root.schema |
199 schema = select.root.schema |
183 toremove = set() |
200 toremove = set() |
184 vargraph = deepcopy(rqlst.vargraph) # graph representing links between variable |
201 vargraph = deepcopy(select.vargraph) # graph representing links between variable |
185 for rel in rqlst.where.get_nodes(nodes.Relation): |
202 for rel in select.where.get_nodes(nodes.Relation): |
186 ovar = _may_be_removed(rel, schema, mainvar) |
203 ovar = _may_be_removed(rel, schema, filtered_variable) |
187 if ovar is not None: |
204 if ovar is not None: |
188 toremove.add(ovar) |
205 toremove.add(ovar) |
189 removed = set() |
206 removed = set() |
190 while toremove: |
207 while toremove: |
191 trvar = toremove.pop() |
208 trvar = toremove.pop() |
197 # remove relation using this variable |
214 # remove relation using this variable |
198 for rel in trvar.stinfo['relations']: |
215 for rel in trvar.stinfo['relations']: |
199 if rel in removed: |
216 if rel in removed: |
200 # already removed |
217 # already removed |
201 continue |
218 continue |
202 rqlst.remove_node(rel) |
219 select.remove_node(rel) |
203 removed.add(rel) |
220 removed.add(rel) |
204 rel = trvar.stinfo['typerel'] |
221 rel = trvar.stinfo['typerel'] |
205 if rel is not None and not rel in removed: |
222 if rel is not None and not rel in removed: |
206 rqlst.remove_node(rel) |
223 select.remove_node(rel) |
207 removed.add(rel) |
224 removed.add(rel) |
208 # cleanup groupby clause |
225 # cleanup groupby clause |
209 if rqlst.groupby: |
226 if select.groupby: |
210 for vref in rqlst.groupby[:]: |
227 for vref in select.groupby[:]: |
211 if vref.name == trvarname: |
228 if vref.name == trvarname: |
212 rqlst.remove_group_var(vref) |
229 select.remove_group_var(vref) |
213 # we can also remove all variables which are linked to this variable |
230 # we can also remove all variables which are linked to this variable |
214 # and have no path to the main variable |
231 # and have no path to the main variable |
215 for ovarname in linkedvars: |
232 for ovarname in linkedvars: |
216 if ovarname == mainvar.name: |
233 if ovarname == filtered_variable.name: |
217 continue |
234 continue |
218 if not has_path(vargraph, ovarname, mainvar.name): |
235 if not has_path(vargraph, ovarname, filtered_variable.name): |
219 toremove.add(rqlst.defined_vars[ovarname]) |
236 toremove.add(select.defined_vars[ovarname]) |
220 |
237 |
221 |
238 |
222 def _may_be_removed(rel, schema, mainvar): |
239 def _may_be_removed(rel, schema, variable): |
223 """if the given relation may be removed from the tree, return the variable |
240 """if the given relation may be removed from the tree, return the variable |
224 on the other side of `mainvar`, else return None |
241 on the other side of `variable`, else return None |
225 Conditions: |
242 Conditions: |
226 * the relation is an attribute selection of the main variable |
243 * the relation is an attribute selection of the main variable |
227 * the relation is optional relation linked to the main variable |
244 * the relation is optional relation linked to the main variable |
228 * the relation is a mandatory relation linked to the main variable |
245 * the relation is a mandatory relation linked to the main variable |
229 without any restriction on the other variable |
246 without any restriction on the other variable |
230 """ |
247 """ |
231 lhs, rhs = rel.get_variable_parts() |
248 lhs, rhs = rel.get_variable_parts() |
232 rschema = schema.rschema(rel.r_type) |
249 rschema = schema.rschema(rel.r_type) |
233 if lhs.variable is mainvar: |
250 if lhs.variable is variable: |
234 try: |
251 try: |
235 ovar = rhs.variable |
252 ovar = rhs.variable |
236 except AttributeError: |
253 except AttributeError: |
237 # constant restriction |
254 # constant restriction |
238 # XXX: X title LOWER(T) if it makes sense? |
255 # XXX: X title LOWER(T) if it makes sense? |
263 if _may_be_removed(orel, schema, ovar) is None: |
280 if _may_be_removed(orel, schema, ovar) is None: |
264 return None |
281 return None |
265 return ovar |
282 return ovar |
266 return None |
283 return None |
267 |
284 |
268 def _make_relation(rqlst, mainvar, rtype, role): |
285 def _make_relation(select, variable, rtype, role): |
269 newvar = rqlst.make_variable() |
286 newvar = select.make_variable() |
270 if role == 'object': |
287 if role == 'object': |
271 rel = nodes.make_relation(newvar, rtype, (mainvar,), nodes.VariableRef) |
288 rel = nodes.make_relation(newvar, rtype, (variable,), nodes.VariableRef) |
272 else: |
289 else: |
273 rel = nodes.make_relation(mainvar, rtype, (newvar,), nodes.VariableRef) |
290 rel = nodes.make_relation(variable, rtype, (newvar,), nodes.VariableRef) |
274 return newvar, rel |
291 return newvar, rel |
275 |
292 |
276 def _add_rtype_relation(rqlst, mainvar, rtype, role): |
293 def _add_rtype_relation(select, variable, rtype, role): |
277 """add a relation relying `mainvar` to entities linked by the `rtype` |
294 """add a relation relying `variable` to entities linked by the `rtype` |
278 relation (where `mainvar` has `role`) |
295 relation (where `variable` has `role`) |
279 |
296 |
280 return the inserted variable for linked entities. |
297 return the inserted variable for linked entities. |
281 """ |
298 """ |
282 newvar, newrel = _make_relation(rqlst, mainvar, rtype, role) |
299 newvar, newrel = _make_relation(select, variable, rtype, role) |
283 rqlst.add_restriction(newrel) |
300 select.add_restriction(newrel) |
284 return newvar, newrel |
301 return newvar, newrel |
285 |
302 |
286 def _add_eid_restr(rel, restrvar, value): |
303 def _add_eid_restr(rel, restrvar, value): |
287 rrel = nodes.make_constant_restriction(restrvar, 'eid', value, 'Int') |
304 rrel = nodes.make_constant_restriction(restrvar, 'eid', value, 'Int') |
288 rel.parent.replace(rel, nodes.And(rel, rrel)) |
305 rel.parent.replace(rel, nodes.And(rel, rrel)) |
289 |
306 |
290 def _remove_relation(rqlst, rel, var): |
307 def _remove_relation(select, rel, var): |
291 """remove a constraint relation from the syntax tree""" |
308 """remove a constraint relation from the syntax tree""" |
292 # remove the relation |
309 # remove the relation |
293 rqlst.remove_node(rel) |
310 select.remove_node(rel) |
294 # remove relations where the filtered variable appears on the |
311 # remove relations where the filtered variable appears on the |
295 # lhs and rhs is a constant restriction |
312 # lhs and rhs is a constant restriction |
296 extra = [] |
313 extra = [] |
297 for vrel in var.stinfo['relations']: |
314 for vrel in var.stinfo['relations']: |
298 if vrel is rel: |
315 if vrel is rel: |
299 continue |
316 continue |
300 if vrel.children[0].variable is var: |
317 if vrel.children[0].variable is var: |
301 if not vrel.children[1].get_nodes(nodes.Constant): |
318 if not vrel.children[1].get_nodes(nodes.Constant): |
302 extra.append(vrel) |
319 extra.append(vrel) |
303 rqlst.remove_node(vrel) |
320 select.remove_node(vrel) |
304 return extra |
321 return extra |
305 |
322 |
306 def _set_orderby(rqlst, newvar, sortasc, sortfuncname): |
323 def _set_orderby(select, newvar, sortasc, sortfuncname): |
307 if sortfuncname is None: |
324 if sortfuncname is None: |
308 rqlst.add_sort_var(newvar, sortasc) |
325 select.add_sort_var(newvar, sortasc) |
309 else: |
326 else: |
310 vref = nodes.variable_ref(newvar) |
327 vref = nodes.variable_ref(newvar) |
311 vref.register_reference() |
328 vref.register_reference() |
312 sortfunc = nodes.Function(sortfuncname) |
329 sortfunc = nodes.Function(sortfuncname) |
313 sortfunc.append(vref) |
330 sortfunc.append(vref) |
314 term = nodes.SortTerm(sortfunc, sortasc) |
331 term = nodes.SortTerm(sortfunc, sortasc) |
315 rqlst.add_sort_term(term) |
332 select.add_sort_term(term) |
316 |
333 |
317 |
334 |
318 _prepare_vocabulary_rqlst = deprecated('[3.13] renamed prepare_vocabulary_rqlst ')( |
335 _prepare_vocabulary_rqlst = deprecated('[3.13] renamed prepare_vocabulary_select')( |
319 prepare_vocabulary_rqlst) |
336 prepare_vocabulary_select) |
320 _cleanup_rqlst = deprecated('[3.13] renamed to cleanup_rqlst')(cleanup_rqlst) |
337 _cleanup_rqlst = deprecated('[3.13] renamed to cleanup_select')(cleanup_select) |
321 |
338 |
322 |
339 |
323 ## base facet classes ########################################################## |
340 ## base facet classes ########################################################## |
324 |
341 |
325 class AbstractFacet(AppObject): |
342 class AbstractFacet(AppObject): |
550 _select_target_entity = True |
576 _select_target_entity = True |
551 |
577 |
552 title = property(rtype_facet_title) |
578 title = property(rtype_facet_title) |
553 no_relation_label = '<no relation>' |
579 no_relation_label = '<no relation>' |
554 |
580 |
|
581 def __repr__(self): |
|
582 return '<%s on (%s-%s)>' % (self.__class__.__name__, self.rtype, self.role) |
|
583 |
|
584 # facet public API ######################################################### |
|
585 |
|
586 def vocabulary(self): |
|
587 """return vocabulary for this facet, eg a list of 2-uple (label, value) |
|
588 """ |
|
589 select = self.select |
|
590 select.save_state() |
|
591 if self.rql_sort: |
|
592 sort = self.sortasc |
|
593 else: |
|
594 sort = None # will be sorted on label |
|
595 try: |
|
596 var = insert_attr_select_relation( |
|
597 select, self.filtered_variable, self.rtype, self.role, |
|
598 self.target_attr, self.sortfunc, sort, |
|
599 self._select_target_entity) |
|
600 if self.target_type is not None: |
|
601 select.add_type_restriction(var, self.target_type) |
|
602 try: |
|
603 rset = self.rqlexec(select.as_string(), self.cw_rset.args) |
|
604 except: |
|
605 self.exception('error while getting vocabulary for %s, rql: %s', |
|
606 self, select.as_string()) |
|
607 return () |
|
608 finally: |
|
609 select.recover() |
|
610 # don't call rset_vocabulary on empty result set, it may be an empty |
|
611 # *list* (see rqlexec implementation) |
|
612 values = rset and self.rset_vocabulary(rset) or [] |
|
613 if self._include_no_relation(): |
|
614 values.insert(0, (self._cw._(self.no_relation_label), '')) |
|
615 return values |
|
616 |
|
617 def possible_values(self): |
|
618 """return a list of possible values (as string since it's used to |
|
619 compare to a form value in javascript) for this facet |
|
620 """ |
|
621 select = self.select |
|
622 select.save_state() |
|
623 try: |
|
624 cleanup_select(select, self.filtered_variable) |
|
625 if self._select_target_entity: |
|
626 prepare_vocabulary_select(select, self.filtered_variable, self.rtype, |
|
627 self.role, select_target_entity=True) |
|
628 else: |
|
629 insert_attr_select_relation( |
|
630 select, self.filtered_variable, self.rtype, self.role, self.target_attr, |
|
631 select_target_entity=False) |
|
632 values = [unicode(x) for x, in self.rqlexec(select.as_string())] |
|
633 except: |
|
634 self.exception('while computing values for %s', self) |
|
635 return [] |
|
636 finally: |
|
637 select.recover() |
|
638 if self._include_no_relation(): |
|
639 values.append('') |
|
640 return values |
|
641 |
|
642 def add_rql_restrictions(self): |
|
643 """add restriction for this facet into the rql syntax tree""" |
|
644 value = self._cw.form.get(self.__regid__) |
|
645 if value is None: |
|
646 return |
|
647 filtered_variable = self.filtered_variable |
|
648 restrvar, rel = _add_rtype_relation(self.select, filtered_variable, |
|
649 self.rtype, self.role) |
|
650 self.value_restriction(restrvar, rel, value) |
|
651 |
|
652 # internal control API ##################################################### |
|
653 |
555 @property |
654 @property |
556 def i18nable(self): |
655 def i18nable(self): |
557 """should label be internationalized""" |
656 """should label be internationalized""" |
558 if self.target_type: |
657 if self.target_type: |
559 eschema = self._cw.vreg.schema.eschema(self.target_type) |
658 eschema = self._cw.vreg.schema.eschema(self.target_type) |
574 sortfunc is set or if we have not to transform the returned value (eg no |
673 sortfunc is set or if we have not to transform the returned value (eg no |
575 label_vid and not i18nable) |
674 label_vid and not i18nable) |
576 """ |
675 """ |
577 return self.sortfunc is not None or (self.label_vid is None |
676 return self.sortfunc is not None or (self.label_vid is None |
578 and not self.i18nable) |
677 and not self.i18nable) |
579 |
|
580 def vocabulary(self): |
|
581 """return vocabulary for this facet, eg a list of 2-uple (label, value) |
|
582 """ |
|
583 rqlst = self.rqlst |
|
584 rqlst.save_state() |
|
585 if self.rql_sort: |
|
586 sort = self.sortasc |
|
587 else: |
|
588 sort = None # will be sorted on label |
|
589 try: |
|
590 mainvar = self.filtered_variable |
|
591 var = insert_attr_select_relation( |
|
592 rqlst, mainvar, self.rtype, self.role, self.target_attr, |
|
593 self.sortfunc, sort, self._select_target_entity) |
|
594 if self.target_type is not None: |
|
595 rqlst.add_type_restriction(var, self.target_type) |
|
596 try: |
|
597 rset = self.rqlexec(rqlst.as_string(), self.cw_rset.args) |
|
598 except: |
|
599 self.exception('error while getting vocabulary for %s, rql: %s', |
|
600 self, rqlst.as_string()) |
|
601 return () |
|
602 finally: |
|
603 rqlst.recover() |
|
604 # don't call rset_vocabulary on empty result set, it may be an empty |
|
605 # *list* (see rqlexec implementation) |
|
606 values = rset and self.rset_vocabulary(rset) or [] |
|
607 if self._include_no_relation(): |
|
608 values.insert(0, (self._cw._(self.no_relation_label), '')) |
|
609 return values |
|
610 |
|
611 def possible_values(self): |
|
612 """return a list of possible values (as string since it's used to |
|
613 compare to a form value in javascript) for this facet |
|
614 """ |
|
615 rqlst = self.rqlst |
|
616 rqlst.save_state() |
|
617 try: |
|
618 cleanup_rqlst(rqlst, self.filtered_variable) |
|
619 if self._select_target_entity: |
|
620 prepare_vocabulary_rqlst(rqlst, self.filtered_variable, self.rtype, |
|
621 self.role, select_target_entity=True) |
|
622 else: |
|
623 insert_attr_select_relation( |
|
624 rqlst, self.filtered_variable, self.rtype, self.role, self.target_attr, |
|
625 select_target_entity=False) |
|
626 values = [unicode(x) for x, in self.rqlexec(rqlst.as_string())] |
|
627 except: |
|
628 self.exception('while computing values for %s', self) |
|
629 return [] |
|
630 finally: |
|
631 rqlst.recover() |
|
632 if self._include_no_relation(): |
|
633 values.append('') |
|
634 return values |
|
635 |
678 |
636 def rset_vocabulary(self, rset): |
679 def rset_vocabulary(self, rset): |
637 if self.i18nable: |
680 if self.i18nable: |
638 _ = self._cw._ |
681 _ = self._cw._ |
639 else: |
682 else: |
812 def add_rql_restrictions(self): |
850 def add_rql_restrictions(self): |
813 """add restriction for this facet into the rql syntax tree""" |
851 """add restriction for this facet into the rql syntax tree""" |
814 value = self._cw.form.get(self.__regid__) |
852 value = self._cw.form.get(self.__regid__) |
815 if not value: |
853 if not value: |
816 return |
854 return |
817 mainvar = self.filtered_variable |
855 filtered_variable = self.filtered_variable |
818 restrvar = _add_rtype_relation(self.rqlst, mainvar, self.rtype, |
856 restrvar = _add_rtype_relation(self.select, filtered_variable, self.rtype, |
819 self.role)[0] |
857 self.role)[0] |
820 self.rqlst.set_distinct(True) |
858 self.select.set_distinct(True) |
821 if isinstance(value, basestring) or self.operator == 'OR': |
859 if isinstance(value, basestring) or self.operator == 'OR': |
822 # only one value selected or multiple ORed values: using IN is fine |
860 # only one value selected or multiple ORed values: using IN is fine |
823 self.rqlst.add_constant_restriction( |
861 self.select.add_constant_restriction( |
824 restrvar, self.target_attr, value, |
862 restrvar, self.target_attr, value, |
825 self.attrtype, self.comparator) |
863 self.attrtype, self.comparator) |
826 else: |
864 else: |
827 # multiple values with AND operator |
865 # multiple values with AND operator |
828 self.rqlst.add_constant_restriction( |
866 self.select.add_constant_restriction( |
829 restrvar, self.target_attr, value.pop(), |
867 restrvar, self.target_attr, value.pop(), |
830 self.attrtype, self.comparator) |
868 self.attrtype, self.comparator) |
831 while value: |
869 while value: |
832 restrvar = _add_rtype_relation(self.rqlst, mainvar, self.rtype, |
870 restrvar = _add_rtype_relation(self.select, filtered_variable, self.rtype, |
833 self.role)[0] |
871 self.role)[0] |
834 self.rqlst.add_constant_restriction( |
872 self.select.add_constant_restriction( |
835 restrvar, self.target_attr, value.pop(), |
873 restrvar, self.target_attr, value.pop(), |
836 self.attrtype, self.comparator) |
874 self.attrtype, self.comparator) |
837 |
875 |
838 |
876 |
839 class AttributeFacet(RelationAttributeFacet): |
877 class AttributeFacet(RelationAttributeFacet): |