def upgrade_to_1004_daterange_widget(context): from eea.facetednavigation.subtypes.interfaces import IFacetedNavigable from eea.facetednavigation.layout.interfaces import IFacetedLayout from eea.facetednavigation.interfaces import ICriteria from eea.facetednavigation.widgets.storage import Criterion brains = api.content.find(object_provides=IFacetedNavigable.__identifier__) layouts = ("faceted-agenda-ungrouped-view-items", "faceted-agenda-view-items") for brain in brains: obj = brain.getObject() if IFacetedLayout(obj).layout not in layouts: continue criterion = ICriteria(obj) for key, criteria in criterion.items(): if criteria.get("widget") != "daterange": continue if criteria.get("usePloneDateFormat") is True: continue logger.info("Upgrade daterange widget for faceted {0}".format(obj)) position = criterion.criteria.index(criteria) values = criteria.__dict__ values["usePloneDateFormat"] = True criterion.criteria[position] = Criterion(**values) criterion.criteria._p_changed = 1
def perPage(self): num_per_page = 20 criteria = ICriteria(self.context) for cid, criterion in criteria.items(): widgetclass = criteria.widget(cid=cid) widget = widgetclass(self.context, self.request, criterion) if widget.widget_type == 'resultsperpage': kwargs = dict((key.replace('[]', ''), val) for key, val in self.request.form.items()) num_per_page = widget.results_per_page(kwargs) return num_per_page
def criteria(self, sort=False, **kwargs): """ Process catalog query """ if self.request: kwargs.update(self.request.form) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict((key.replace('[]', ''), val) for key, val in kwargs.items()) logger.debug("REQUEST: %r", kwargs) # Generate the catalog query criteria = ICriteria(self.context) query = {} for cid, criterion in criteria.items(): widget = criteria.widget(cid=cid) widget = widget(self.context, self.request, criterion) widget_query = widget.query(kwargs) if getattr(widget, 'faceted_field', False): widget_index = widget.data.get('index', '') if ('facet.field' in query and widget_index not in query['facet.field']): query['facet.field'].append(widget_index) else: query['facet.field'] = [widget_index] query.update(widget_query) # Handle language widgets if criterion.get('index', '') == 'Language': language_widget = queryMultiAdapter((widget, self.context), ILanguageWidgetAdapter) if not language_widget: continue query.update(language_widget(kwargs)) # Add default sorting criteria if sort and 'sort_on' not in query: query['sort_on'] = 'effective' query['sort_order'] = 'reverse' # Add default language. # Also make sure to return language-independent content. lang = self.language if lang: lang = [lang, ''] query.setdefault('Language', lang) logger.debug('QUERY: %s', query) return query
def criteria(self, sort=False, **kwargs): """ Process catalog query """ if self.request: kwargs.update(self.request.form) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict((key.replace('[]', ''), val) for key, val in kwargs.items()) logger.debug("REQUEST: %r", kwargs) # Generate the catalog query criteria = ICriteria(self.context) query = {} for cid, criterion in criteria.items(): widget = criteria.widget(cid=cid) widget = widget(self.context, self.request, criterion) widget_query = widget.query(kwargs) if getattr(widget, 'faceted_field', False): widget_index = widget.data.get('index', '') if ('facet.field' in query and widget_index not in query['facet.field']): query['facet.field'].append(widget_index) else: query['facet.field'] = [widget_index] query.update(widget_query) # Handle language widgets if criterion.get('index', '') == 'Language': language_widget = queryMultiAdapter((widget, self.context), ILanguageWidgetAdapter) if not language_widget: continue query.update(language_widget(kwargs)) # Add default sorting criteria if sort and not query.has_key('sort_on'): query['sort_on'] = 'effective' query['sort_order'] = 'reverse' # Add default language. # Also make sure to return language-independent content. lang = self.language if lang: lang = [lang, ''] query.setdefault('Language', lang) logger.debug('QUERY: %s', query) return query
def query(self, batch=True, sort=False, **kwargs): """ Search using given criteria """ if self.request: kwargs.update(self.request.form) kwargs.pop('sort[]', None) kwargs.pop('sort', None) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict( (key.replace('[]', ''), val) for key, val in kwargs.items()) #fix for unicode error in indexes for key, val in kwargs.items(): if isinstance(val, str): kwargs[key] = val.decode('utf-8') query = self.criteria(sort=sort, **kwargs) # We don't want to do an unnecessary sort for a counter query counter_query = kwargs.pop('counter_query', False) if counter_query: query.pop('sort_on', None) query.pop('sort_order', None) catalog = getUtility(IFacetedCatalog) num_per_page = 20 criteria = ICriteria(self.context) brains_filters = [] for cid, criterion in criteria.items(): widgetclass = criteria.widget(cid=cid) widget = widgetclass(self.context, self.request, criterion) if widget.widget_type == 'resultsperpage': num_per_page = widget.results_per_page(kwargs) brains_filter = queryAdapter(widget, IWidgetFilterBrains) if brains_filter: brains_filters.append(brains_filter) b_start = safeToInt(kwargs.get('b_start', 0)) orphans = num_per_page * 20 / 100 # orphans = 20% of items per page if batch and not brains_filters: # add b_start and b_size to query to use better sort algorithm query['b_start'] = b_start query['b_size'] = num_per_page + orphans try: brains = catalog(self.context, **query) except Exception, err: logger.exception(err) return Batch([], 20, 0)
def criteria(self, sort=True, **kwargs): """ Process catalog query """ if self.request: kwargs.update(self.request.form) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict((key.replace('[]', ''), val) for key, val in kwargs.items()) logger.debug("REQUEST: %r", kwargs) # Generate the catalog query mtool = getToolByName(self.context, 'portal_membership', None) criteria = ICriteria(self.context) query = {} if mtool.isAnonymousUser(): query['review_state'] = 'published' for cid, criterion in criteria.items(): widget = criteria.widget(cid=cid) widget = widget(self.context, self.request, criterion) query.update(widget.query(kwargs)) # Handle language widgets if criterion.get('index', '') == 'Language': language_widget = queryMultiAdapter((widget, self.context), ILanguageWidgetAdapter) if not language_widget: continue query.update(language_widget(kwargs)) # Add default sorting criteria if sort and not query.has_key('sort_on'): query['sort_on'] = 'effective' query['sort_order'] = 'reverse' # Add default language. # Also make sure to return language-independent content. lang = self.language if lang: lang = [lang, ''] query.setdefault('Language', lang) logger.debug('QUERY: %s', query) return query
def upgrade_to_3(context): catalog = api.portal.get_tool('portal_catalog') brains = catalog(object_provides=IFacetedNavigable.__identifier__) for brain in brains: obj = brain.getObject() criterias = ICriteria(obj) changes = False for cid, crit in criterias.items(): if crit.get('vocabulary', u'') in (u'imio.dashboard.conditionawarecollectionvocabulary', u'imio.dashboard.cachedcollectionvocabulary'): crit.vocabulary = u'collective.eeafaceted.collectionwidget.cachedcollectionvocabulary' changes = True logger.info('Criterion {} updated on object {}'.format(cid, brain.getPath())) if changes: criterias.criteria._p_changed = 1
def query(self, batch=True, sort=False, **kwargs): """ Search using given criteria """ if self.request: kwargs.update(self.request.form) kwargs.pop('sort[]', None) kwargs.pop('sort', None) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict((key.replace('[]', ''), val) for key, val in kwargs.items()) query = self.criteria(sort=sort, **kwargs) # We don't want to do an unnecessary sort for a counter query counter_query = kwargs.pop('counter_query', False) if counter_query: query.pop('sort_on', None) query.pop('sort_order', None) catalog = getUtility(IFacetedCatalog) num_per_page = 20 criteria = ICriteria(self.context) brains_filters = [] for cid, criterion in criteria.items(): widgetclass = criteria.widget(cid=cid) widget = widgetclass(self.context, self.request, criterion) if widget.widget_type == 'resultsperpage': num_per_page = widget.results_per_page(kwargs) brains_filter = queryAdapter(widget, IWidgetFilterBrains) if brains_filter: brains_filters.append(brains_filter) b_start = safeToInt(kwargs.get('b_start', 0)) orphans = num_per_page * 20 / 100 # orphans = 20% of items per page if batch and not brains_filters: # add b_start and b_size to query to use better sort algorithm query['b_start'] = b_start query['b_size'] = num_per_page + orphans try: brains = catalog(self.context, **query) except Exception, err: logger.exception(err) return Batch([], 20, 0)
def query(self, form): """ Get value from form and return a catalog dict query """ query = {} # import ipdb; ipdb.set_trace() index = self.data.get("index", "") moreorless = self.data.get("moreorless", "") index = index.encode("utf-8", "replace") value = None if not index: return query if self.hidden: value = self.default else: value = form.get(self.data.getId(), "") if not value: return query # check if there are other criteria with same index second_value = None second_moreorless = None criteria = ICriteria(self.context) for cid, criterion in criteria.items(): if cid in form.keys() and cid != self.data.getId(): if criterion.index == index: second_value = form.get(cid) second_moreorless = criterion.moreorless value = int(value) # portal_catalog({'price':{'query':[2,1000],'range':'min:max'}}) if moreorless == u"more" and not second_value: range = "min" elif moreorless == u"less" and not second_value: range = "max" else: range = "min:max" if second_moreorless == u"more": value = [int(second_value), value] query[index] = {"query": value, "range": range} return query
def update_dashboards(self): # update daterange criteria brains = api.content.find( object_provides=IFacetedNavigable.__identifier__) for brain in brains: obj = brain.getObject() criterion = ICriteria(obj) for key, criteria in criterion.items(): if criteria.get("widget") != "daterange": continue if criteria.get("usePloneDateFormat") is True: continue logger.info( "Upgrade daterange widget for faceted {0}".format(obj)) position = criterion.criteria.index(criteria) values = criteria.__dict__ values["usePloneDateFormat"] = True values["labelStart"] = u'Start date' values["labelEnd"] = u'End date' criterion.criteria[position] = Criterion(**values) criterion.criteria._p_changed = 1
def criteria(self, sort=False, **kwargs): """ Process catalog query """ if self.request: kwargs.update(self.request.form) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict((key.replace('[]', ''), val) for key, val in kwargs.items()) logger.debug('REQUEST: %r', kwargs) # Generate the catalog query criteria = ICriteria(self.context) query = {} for cid, criterion in criteria.items(): widget = criteria.widget(cid=cid) widget = widget(self.context, self.request, criterion) widget_query = widget.query(kwargs) if getattr(widget, 'faceted_field', False): widget_index = widget.data.get('index', '') if ('facet.field' in query and widget_index not in query['facet.field']): query['facet.field'].append(widget_index) else: query['facet.field'] = [widget_index] query.update(widget_query) # Add default sorting criteria if sort and 'sort_on' not in query: query['sort_on'] = 'effective' query['sort_order'] = 'reverse' if 'Language' in query: query.pop('Language') logger.debug('QUERY: %s', query) return query
def query(self, batch=True, sort=False, **kwargs): """ Search using given criteria """ if self.request: kwargs.update(self.request.form) kwargs.pop('sort[]', None) kwargs.pop('sort', None) # jQuery >= 1.4 adds type to params keys # $.param({ a: [2,3,4] }) // "a[]=2&a[]=3&a[]=4" # Let's fix this kwargs = dict((key.replace('[]', ''), val) for key, val in kwargs.items()) query = self.criteria(sort=sort, **kwargs) # We don't want to do an unnecessary sort for a counter query counter_query = kwargs.pop('counter_query', False) if counter_query: query.pop('sort_on', None) query.pop('sort_order', None) catalog = getUtility(IFacetedCatalog) num_per_page = 20 criteria = ICriteria(self.context) brains_filters = [] for cid, criterion in criteria.items(): widgetclass = criteria.widget(cid=cid) widget = widgetclass(self.context, self.request, criterion) if widget.widget_type == 'resultsperpage': num_per_page = widget.results_per_page(kwargs) brains_filter = queryAdapter(widget, IWidgetFilterBrains) if brains_filter: brains_filters.append(brains_filter) b_start = safeToInt(kwargs.get('b_start', 0)) # make sure orphans is an integer, // is used so in Python3 we have an # integer division as by default, a division result is a float orphans = num_per_page * 20 // 100 # orphans = 20% of items per page if batch and not brains_filters: # add b_start and b_size to query to use better sort algorithm query['b_start'] = b_start query['b_size'] = num_per_page + orphans try: brains = catalog(self.context, **query) except Exception as err: logger.exception(err) return Batch([], 20, 0) if not brains: return Batch([], 20, 0) # Apply after query (filter) on brains start = time.time() for brains_filter in brains_filters: brains = brains_filter(brains, kwargs) if not batch: return brains if isinstance(brains, GeneratorType): brains = [brain for brain in brains] delta = time.time() - start if delta > 30: logger.warn("Very slow IWidgetFilterBrains adapters: %s at %s", brains_filters, self.context.absolute_url()) return Batch(brains, num_per_page, b_start, orphan=orphans)
class CollectionWidget(RadioWidget): """A widget listing collections used as base query.""" widget_type = 'collection-link' widget_label = 'Collection Link' faceted_field = False index = ViewPageTemplateFile('widget.pt') css_class = 'faceted-tagscloud-collection-widget' category_vocabulary = ( 'collective.eeafaceted.collectionwidget.collectioncategoryvocabulary' ) def __init__(self, context, request, data=None): super(CollectionWidget, self).__init__(context, request, data) # real context could not be current context but some distant context # look in eea.facetednavigation.criteria.handler.Criteria self.criteria = ICriteria(self.context) self.context = self.criteria.context # display the fieldset around the widget when rendered? self.display_fieldset = True def update(self): """Remove fields 'index' and 'catalog', unused.""" super(CollectionWidget, self).update() default_group = self.groups[0] if 'index' in default_group.fields: del default_group.fields['index'] if 'catalog' in default_group.widgets: del default_group.fields['catalog'] if 'index' in default_group.widgets: del default_group.widgets['index'] if 'catalog' in default_group.widgets: del default_group.widgets['catalog'] def _initialize_widget(self): """ """ self.grouped_vocabulary = self._generate_vocabulary() def __call__(self, **kwargs): # compute the vocabulary used in the widget self._initialize_widget() return super(CollectionWidget, self).__call__(**kwargs) def query(self, form): """ Get value from form and return a catalog dict query """ # we receive the UID of the selected Collection # get the collection, compute the query and return it collection_uid = form.get(self.data.__name__, '') if collection_uid and not collection_uid == 'all': # get the collection and compute the query catalog = getToolByName(self.context, 'portal_catalog') brains = catalog(UID=collection_uid) collection = brains[0].getObject() query = queryparser.parseFormquery(collection, collection.query) # use sort_on defined on the collection if it is # not already in the request.form # get the sort_on criterion and look in the request.form if it is used sort_on_is_used = False for criterion_id, criterion in self.criteria.items(): if criterion.widget == SortingWidget.widget_type: # criterion id in the request.form is like c0[] if "{0}[]".format(criterion_id) in self.request.form: sort_on_is_used = True break if not sort_on_is_used: if collection.sort_on: query['sort_on'] = collection.sort_on if collection.sort_reversed: query['sort_order'] = collection.sort_reversed and 'descending' or '' return query return {} def count(self, brains, sequence=None): """ """ res = {} if not sequence: sequence = [term.token for term in self.vocabulary()] catalog = getToolByName(self.context, 'portal_catalog') for value in sequence: if not value: res[value] = len(brains) continue res[value] = len( catalog(self.query(form={self.data.__name__: value}))) return res @property @memoize def default(self): """Return the default value""" default = super(CollectionWidget, self).default if not default: # it is possible to not select a default, it will have # same behaviour as selecting option "All" return default # call an adapter to get the correct value return self.adapter_default_value @property def adapter_default_value(self): adapter = queryMultiAdapter((self.context, self.request, self), IWidgetDefaultValue) if adapter: return adapter.value @property def default_term_value(self): idx = self.sortreversed and -1 or 0 terms = self.portal_vocabulary() if len(terms) > 0: return terms[idx][0] def kept_criteria_as_json(self, collection_uid): '''Given a p_collectionUID, get indexes managed by the collection.''' adapter = queryMultiAdapter((self.context, self), IKeptCriteria) res = adapter.compute(collection_uid) # DateTime are not json serializable, we convert them before for k, v in res.iteritems(): if isinstance(v, DateTime): res[k] = v.ISO() return json.dumps(res) @property def advanced_criteria(self): '''Returns a dict containing advanced criteria, the key is the criterion id and the value is the managed index.''' faceted_config = queryMultiAdapter((self.context, self.request), name='configure_faceted.html') advanced_criteria = {} for criterion in faceted_config.get_criteria(): if criterion.section == u'advanced': advanced_criteria[criterion.getId()] = criterion.index return advanced_criteria @property def advanced_criteria_as_json(self): return json.dumps(self.advanced_criteria.keys()) @property def sortreversed(self): return bool(int(getattr(self.data, 'sortreversed', u'0') or u'0')) @property def hidealloption(self): return bool(int(getattr(self.data, 'hidealloption', u'0') or u'0')) @property @memoize def categories(self): factory = getUtility(IVocabularyFactory, self.category_vocabulary) voc = factory(self.context) return voc def vocabulary(self): voc_id = self.data.get('vocabulary', None) voc = queryUtility(IVocabularyFactory, voc_id, None) if voc is None: return [] return list(voc(self.context)) def _generate_vocabulary(self): voc = OrderedDict() # empty category voc[''] = {'collections': []} for term in self.categories: voc[term.token] = {'term': term, 'collections': []} categories_token = [term.token for term in self.categories] for term in self.vocabulary(): parent = aq_parent(term.value) # collections directly added to context, no intermediate category if parent == self.context and parent.UID() not in categories_token: category = '' elif parent.UID() in categories_token: category = parent.UID() else: # parent is not visible, a subfolder private for current user continue voc[category]['collections'].append(term) # remove empty categories res = OrderedDict() for k, v in voc.items(): if v['collections']: res[k] = v return res