def test__start_end_from_mode(self): from plone.app.event.base import start_end_from_mode from plone.app.event.base import dt_end_of_day start, end = start_end_from_mode('all') self.assertTrue(start is None and end is None) start, end = start_end_from_mode('past') self.assertTrue(start is None and isinstance(end, datetime.datetime)) start, end = start_end_from_mode('future') self.assertTrue(isinstance(start, datetime.datetime) and end is None) start, end = start_end_from_mode('now') self.assertTrue(isinstance(start, datetime.datetime) and isinstance(end, datetime.datetime) and end.hour==23 and end.minute==59 and end.second==59) start, end = start_end_from_mode('7days') self.assertTrue(isinstance(start, datetime.datetime) and isinstance(end, datetime.datetime) and end == dt_end_of_day(start+datetime.timedelta(days=7))) start, end = start_end_from_mode('today') self.assertTrue(isinstance(start, datetime.datetime) and isinstance(end, datetime.datetime) and start.hour==0 and start.minute==0 and start.second==0 and end.hour==23 and end.minute==59 and end.second==59 and (start, end) == start_end_from_mode('day')) day = datetime.datetime(2013,2,1,18,22) start, end = start_end_from_mode('day', day) self.assertTrue(start.date() == day.date() == end.date() and start.hour==0 and start.minute==0 and start.second==0 and end.hour==23 and end.minute==59 and end.second==59) # test with date-only day = datetime.datetime(2013,2,1) start, end = start_end_from_mode('day', day) self.assertTrue(start.date() == day.date() == end.date() and start.hour==0 and start.minute==0 and start.second==0 and end.hour==23 and end.minute==59 and end.second==59)
def results(self, custom_query, request_params): # Support for the Event Listing view from plone.app.event collection_layout = self.context.getLayout() default_view = self.context.restrictedTraverse(collection_layout) if isinstance(default_view, EventListing): mode = request_params.get("mode", "future") date = request_params.get("date", None) date = guess_date_from(date) if date else None start, end = start_end_from_mode(mode, date, self.collection) start, end = _prepare_range(self.collection, start, end) custom_query.update(start_end_query(start, end)) # TODO: expand events. better yet, let collection.results # do that return self.collection.results( batch=False, brains=True, custom_query=custom_query )
def get_events(self, start=None, end=None, batch=True, mode=None): context = self.context mode = mode or self.mode if not mode and not start and not end: mode = "future" if mode: dt = None if self.date: try: dt = guess_date_from(self.date) except TypeError: pass start, end = start_end_from_mode(mode, dt, context) b_start = b_size = None if batch: b_start = self.b_start b_size = self.b_size occs = get_occurrences_from_brains( context, get_portal_events( context, start, end, # b_start=b_start, b_size=b_size, path=context.getPhysicalPath(), ), start, end, ) if batch: ret = Batch(occs, size=b_size, start=b_start, orphan=self.orphan) else: ret = occs return ret
def _get_occs(self): date = guess_date_from(self.date) if date: start, end = start_end_from_mode('day', date, self.context) query = {} query['review_state'] = self.data.state search_base_path = self.search_base_path if search_base_path: query['path'] = {'query': search_base_path} list_events = [] events = get_events(self.context, start=start, end=end, sort='start', sort_reverse=False, ret_mode=RET_MODE_OBJECTS, expand=True, **query) today = datetime.datetime.today().date() for occ in events: if IOccurrence.providedBy(occ): occurrence_id = occ.id event = aq_parent(occ) occ_data = ITicketOccurrenceData(event) occs = occ_data.ticket_occurrences(occurrence_id) if occs: occurrence_ticket = occs[0] item_stock = get_item_stock(occurrence_ticket) if item_stock: stock = item_stock.available else: stock = 0 is_today = occ.start.date() == today new_event = { "start": occ.start, "uid": occurrence_ticket.UID(), "stock": stock, "is_today": is_today } list_events.append(new_event) elif IBuyableEvent.providedBy(occ): occ_data = ITicketOccurrenceData(occ) occs = occ_data.tickets if occs: occurrence_ticket = occs[0] item_stock = get_item_stock(occurrence_ticket) if item_stock: stock = item_stock.available else: stock = 0 is_today = occ.start.date() == today new_event = { "start": occ.start, "uid": occurrence_ticket.UID(), "stock": stock, "is_today": is_today } list_events.append(new_event) else: print 'NOT AVAILABLE' return list_events else: return []
def _start_end(self): start, end = start_end_from_mode(self.mode, self.date, self.context) return start, end
def test__start_end_from_mode(self): from plone.app.event.base import start_end_from_mode from plone.app.event.base import dt_end_of_day # ALL # start, end = start_end_from_mode('all') self.assertTrue(start is None and end is None) # PAST # start, end = start_end_from_mode('past') self.assertTrue(start is None and isinstance(end, datetime)) # FUTURE # start, end = start_end_from_mode('future') self.assertTrue(isinstance(start, datetime) and end is None) # NOW # start, end = start_end_from_mode('now') self.assertTrue( isinstance(start, datetime) and isinstance(end, datetime) and end.hour == 23 and end.minute == 59 and end.second == 59 ) # 7DAYS # start, end = start_end_from_mode('7days') self.assertTrue( isinstance(start, datetime) and isinstance(end, datetime) and end == dt_end_of_day(start + timedelta(days=6)) ) # TODAY # start, end = start_end_from_mode('today') self.assertTrue( isinstance(start, datetime) and isinstance(end, datetime) and start.hour == 0 and start.minute == 0 and start.second == 0 and end.hour == 23 and end.minute == 59 and end.second == 59 and (start, end) == start_end_from_mode('day') ) # DAY # day = datetime(2013, 2, 1, 18, 22) start, end = start_end_from_mode('day', day) self.assertTrue( start.date() == day.date() == end.date() and start.hour == 0 and start.minute == 0 and start.second == 0 and end.hour == 23 and end.minute == 59 and end.second == 59 ) # test with date-only day = datetime(2013, 2, 1) start, end = start_end_from_mode('day', day) self.assertTrue( start.date() == day.date() == end.date() and start.hour == 0 and start.minute == 0 and start.second == 0 and end.hour == 23 and end.minute == 59 and end.second == 59 ) # WEEK # def ret_0(): return 0 # Monday def ret_1(): return 1 # Tuesday def ret_6(): return 6 # Sunday # prepare patched first_weekday orig_first_weekday = base.first_weekday base.first_weekday = ret_0 day = datetime(2013, 2, 2) start, end = start_end_from_mode('week', day) self.assertTrue( start.isoformat() == '2013-01-28T00:00:00' and end.isoformat() == '2013-02-03T23:59:59' ) base.first_weekday = ret_1 day = datetime(2013, 2, 2) start, end = start_end_from_mode('week', day) self.assertTrue( start.isoformat() == '2013-01-29T00:00:00' and end.isoformat() == '2013-02-04T23:59:59' ) base.first_weekday = ret_6 day = datetime(2013, 2, 1) start, end = start_end_from_mode('week', day) self.assertTrue( start.isoformat() == '2013-01-27T00:00:00' and end.isoformat() == '2013-02-02T23:59:59' ) base.first_weekday = orig_first_weekday # restore orig first_weekday # MONTH # start, end = start_end_from_mode('month') self.assertTrue(start < end and start.day == 1) day = datetime(2013, 2, 7) start, end = start_end_from_mode('month', day) self.assertTrue( start.year == 2013 and start.month == 2 and start.day == 1 and start.hour == 0 and start.minute == 0 and start.second == 0 and end.year == 2013 and end.month == 2 and end.day == 28 and end.hour == 23 and end.minute == 59 and end.second == 59 )
def get_filter_items(target_collection, group_by, filter_type=DEFAULT_FILTER_TYPE, narrow_down=False, show_count=False, view_name='', cache_enabled=True, request_params=None): request_params = request_params or {} custom_query = {} # Additional query to filter the collection collection = uuidToObject(target_collection) if not collection or not group_by: return None collection_url = collection.absolute_url() # Recursively transform all to unicode request_params = safe_decode(request_params) # Support for the Event Listing view from plone.app.event collection_layout = collection.getLayout() default_view = collection.restrictedTraverse(collection_layout) if isinstance(default_view, EventListing): mode = request_params.get('mode', 'future') date = request_params.get('date', None) date = guess_date_from(date) if date else None start, end = start_end_from_mode(mode, date, collection) start, end = _prepare_range(collection, start, end) custom_query.update(start_end_query(start, end)) # TODO: expand events. better yet, let collection.results # do that # Get index in question and the current filter value of this index, if set. groupby_criteria = getUtility(IGroupByCriteria).groupby idx = groupby_criteria[group_by]['index'] current_idx_value = safe_iterable(request_params.get(idx)) extra_ignores = [] if not narrow_down: # Additive filtering is about adding other filter values of the same # index. extra_ignores = [idx, idx + '_op'] urlquery = base_query(request_params, extra_ignores) # Get all collection results with additional filter defined by urlquery custom_query.update(urlquery) custom_query = make_query(custom_query) catalog_results = ICollection(collection).results( batch=False, brains=True, custom_query=custom_query) if narrow_down and show_count: # we need the extra_ignores to get a true count # even when narrow_down filters the display of indexed values # count_query allows us to do that true count count_query = {} count_urlquery = base_query(request_params, [idx, idx + '_op']) count_query.update(count_urlquery) catalog_results_fullcount = ICollection(collection).results( batch=False, brains=True, custom_query=count_query) if not catalog_results: return None # Attribute name for getting filter value from brain metadata_attr = groupby_criteria[group_by]['metadata'] # Optional modifier to set title from filter value display_modifier = groupby_criteria[group_by].get('display_modifier', None) # CSS modifier to set class on filter item css_modifier = groupby_criteria[group_by].get('css_modifier', None) # Value blacklist value_blacklist = groupby_criteria[group_by].get('value_blacklist', None) # Allow value_blacklist to be callables for runtime-evaluation value_blacklist = value_blacklist() if callable( value_blacklist) else value_blacklist # noqa # fallback to title sorted values sort_key_function = groupby_criteria[group_by].get( 'sort_key_function', lambda it: it['title'].lower()) grouped_results = {} for brain in catalog_results: # Get filter value val = getattr(brain, metadata_attr, None) if callable(val): val = val() # decode it to unicode val = safe_decode(val) # Make sure it's iterable, as it's the case for e.g. the subject index. val = safe_iterable(val) for filter_value in val: if filter_value is None or isinstance(filter_value, Missing): continue if value_blacklist and filter_value in value_blacklist: # Do not include blacklisted continue if filter_value in grouped_results: # Add counter, if filter value is already present grouped_results[filter_value]['count'] += 1 continue # Set title from filter value with modifications, # e.g. uuid to title title = filter_value if filter_value is not EMPTY_MARKER and callable(display_modifier): title = safe_decode(display_modifier(filter_value)) # Build filter url query _urlquery = urlquery.copy() # Allow deselection if filter_value in current_idx_value: _urlquery[idx] = [ it for it in current_idx_value if it != filter_value ] elif filter_type != 'single': # additive filter behavior _urlquery[idx] = current_idx_value + [filter_value] _urlquery[idx + '_op'] = filter_type # additive operator else: _urlquery[idx] = filter_value query_param = urlencode(safe_encode(_urlquery), doseq=True) url = '/'.join([ it for it in [ collection_url, view_name, '?' + query_param if query_param else None ] if it ]) # Set selected state selected = filter_value in current_idx_value css_class = 'filterItem {0}{1} {2}'.format( 'filter-' + idnormalizer.normalize(filter_value), ' selected' if selected else '', css_modifier(filter_value) if css_modifier else '', ) grouped_results[filter_value] = { 'title': title, 'url': url, 'value': filter_value, 'css_class': css_class, 'count': 1, 'selected': selected } # Entry to clear all filters urlquery_all = { k: v for k, v in list(urlquery.items()) if k not in (idx, idx + '_op') } if narrow_down and show_count: catalog_results = catalog_results_fullcount ret = [{ 'title': translate(_('subject_all', default=u'All'), context=getRequest()), 'url': u'{0}/?{1}'.format(collection_url, urlencode(safe_encode(urlquery_all), doseq=True)), 'value': 'all', 'css_class': 'filterItem filter-all', 'count': len(catalog_results), 'selected': idx not in request_params }] grouped_results = list(grouped_results.values()) if callable(sort_key_function): grouped_results = sorted(grouped_results, key=sort_key_function) ret += grouped_results return ret
def _results(self, collection, request_params): ret = [] if collection: collection_layout = collection.getLayout() default_view = collection.restrictedTraverse(collection_layout) results = [] custom_query = {} if isinstance(default_view, EventListing): mode = request_params.get('mode', 'future') date = request_params.get('date', None) date = guess_date_from(date) if date else None start, end = start_end_from_mode(mode, date, collection) start, end = _prepare_range(collection, start, end) custom_query.update(start_end_query(start, end)) # TODO: expand events. better yet, let collection.results # do that idx = GROUPBY_CRITERIA[self.data.group_by]['index'] urlquery = {} urlquery.update(request_params) for it in (idx, 'b_start', 'b_size', 'batch', 'sort_on', 'limit'): # Remove problematic url parameters # And make sure to not filter by previously selected terms from # this index. This narrows down too much (except for dedicated # facetted searches - TODO) if it in urlquery: del urlquery[it] custom_query.update(urlquery) results = collection.results( batch=False, custom_query=custom_query ) if results: ret.append(dict( title=_('subject_all', default=u'All'), url=u'{0}/?{1}'.format( self.collection.absolute_url(), urlencode(urlquery) ), count=len(results), selected=idx not in request_params )) attr = GROUPBY_CRITERIA[self.data.group_by]['metadata'] mod = GROUPBY_CRITERIA[self.data.group_by]['display_modifier'] grouped_results = {} for item in results: val = getattr(item, attr, None) if callable(val): val = val() if not getattr(val, '__iter__', False): val = [val] for crit in val: if crit not in grouped_results: urlquery[idx] = crit title = _(safe_decode( mod(crit) if mod and crit is not EMPTY_MARKER else crit )) # mod modifies for displaying (e.g. uuid to title) # noqa url = u'{0}/?{1}'.format( self.collection.absolute_url(), urlencode(safe_encode(urlquery)) # need to be utf-8 encoded # noqa ) selected = safe_decode(request_params.get(idx)) == safe_decode(crit) # noqa sort_key = crit if crit else 'zzzzzz' crit_dict = { 'sort_key': sort_key.lower(), 'count': 1, 'title': title, 'url': url, 'selected': selected } grouped_results[crit] = crit_dict else: grouped_results[crit]['count'] += 1 ret += sorted( grouped_results.values(), key=lambda it: it['sort_key'] ) return ret