def filter_query(self, query): query = super(Search, self).filter_query(query) if query: if query['path'] == getNavigationRoot( self.context) or query['path'] is None: query['path'] = search_paths() log.debug('Make general path search, request was for "%s".', getNavigationRoot(self.context)) else: log.debug('Make specific path ("%s") search.', query['path']) query['portal_type'] += self.extra_types() log.debug("Search Query: %s", query) return query
def objects(self): """ Overrides the SiteMapView method """ catalog = getToolByName(self.context, 'portal_catalog') root = getNavigationRoot(self.context) query = { 'Language': 'all', 'path': root, 'b_size': 10000, } results = catalog.searchResults(query) if None in results: query['b_size'] = len(results) results = catalog.searchResults(query) for item in results: location = item.getURL() map_item = { 'loc' : location, 'lastmod' : item.modified.ISO8601(), } if ("rezensionen/zeitschriften/francia-recensio" in location or "rezensionen/zeitschriften/sehepunkte" in location) \ and item.portal_type in ["Review Monograph", "Review Journal"]: map_item['priority'] = 0.1 yield map_item
def _makequery(self, query=None, batch=False, b_start=0, b_size=30, sort_on=None, sort_order=None, limit=0, brains=False): """Parse the (form)query and return using multi-adapter""" parsedquery = queryparser.parseFormquery( self.context, query, sort_on, sort_order, catalog_name=self.catalog_name, kwargs=self.contentFilter) if not parsedquery: if brains: return [] else: return IContentListing([]) catalog = getToolByName(self.context, self.catalog_name) if batch: parsedquery['b_start'] = b_start parsedquery['b_size'] = b_size elif limit: parsedquery['sort_limit'] = limit if 'path' not in parsedquery: parsedquery['path'] = {'query': ''} parsedquery['path']['query'] = getNavigationRoot(self.context) + \ parsedquery['path']['query'] results = catalog(parsedquery) if not brains: results = IContentListing(results) if batch: results = Batch(results, b_size, b_start) return results
def _path(context, row): values = row.values depth = None if '::' in values: values, _depth = values.split('::', 1) try: depth = int(_depth) except ValueError: pass if not '/' in values: # It must be a UID values = '/'.join(getPathByUID(context, values)) # take care of absolute paths without nav_root nav_root = getNavigationRoot(context) if not values.startswith(nav_root): values = nav_root + values query = {} if depth is not None: query['depth'] = depth # when a depth value is specified, a trailing slash matters on the # query values = values.rstrip('/') query['query'] = [values] return {row.index: query}
def _makequery(self, query=None, batch=False, b_start=0, b_size=30, sort_on=None, sort_order=None, limit=0, brains=False): """Parse the (form)query and return using multi-adapter""" parsedquery = queryparser.parseFormquery( self.context, query, sort_on, sort_order) if not parsedquery: if brains: return [] else: return IContentListing([]) catalog = getToolByName(self.context, self.catalog_name) if batch: parsedquery['b_start'] = b_start parsedquery['b_size'] = b_size elif limit: parsedquery['sort_limit'] = limit if 'path' not in parsedquery: parsedquery['path'] = {'query': ''} parsedquery['path']['query'] = getNavigationRoot(self.context) + \ parsedquery['path']['query'] results = catalog(parsedquery) if not brains: results = IContentListing(results) if batch: results = Batch(results, b_size, b_start) return results
def _path(context, row): values = row.values[0] depth = None if '::' in values: values, _depth = values.split('::', 1) try: depth = int(_depth) except ValueError: pass if not '/' in values: # It must be a UID values = '/'.join(getPathByUID(context, values)) # take care of absolute paths without nav_root nav_root = getNavigationRoot(context) if not values.startswith(nav_root): values = nav_root + values query = {} if depth is not None: query['depth'] = depth # when a depth value is specified, a trailing slash matters on the # query values = values.rstrip('/') query['query'] = [values] return {row.index: query}
def search_catalog_results(context, q, limit, path): ploneUtils = getToolByName(context, 'plone_utils') # generate a result set for the query catalog = context.portal_catalog friendly_types = ploneUtils.getUserFriendlyTypes() # for now we just do a full search to prove a point, this is not the # way to do this in the future, we'd use a in-memory probability based # result set. # convert queries to zctextindex # XXX really if it contains + * ? or - # it will not be right since the catalog ignores all non-word # characters equally like # so we don't even attept to make that right. # But we strip these and these so that the catalog does # not interpret them as metachars # See http://dev.plone.org/plone/ticket/9422 for an explanation of '\u3000' q = our_unicode(q) r = prepare_search_string(q) params = { 'SearchableText': r, 'portal_type': friendly_types, 'sort_limit': limit + 1, 'review_state': "published", } params2 = { 'Subject': q, 'portal_type': friendly_types, 'sort_limit': limit + 1, 'review_state': "published", } if path is None: # useful for subsites params2['path'] = params['path'] = getNavigationRoot(context) else: params2['path'] = params['path'] = path # We join the results of both queries and get rid of duplicates (duplicates # can appear when the query is found both in text and in Subject). The # original idea was to convert them to sets, but this doesn't work as the # brain items aren't equivalent. One possibility would be to get all # objects (then sets would work), or we manually get rid of duplicates # (based on ID's) results1 = catalog(**params) results2 = catalog(**params2) results = [] result_ids = [] for brain in results1 + results2: if brain.id not in result_ids: results.append(brain) result_ids.append(brain.id) return results
def get_referer_path(context, request): if referer_is_current(request): return getNavigationRoot(context) try: return request.getHeader('referer').replace(get_site_url(context), get_site_path(context)) except (AttributeError, TypeError): return None
def get_referer_path(context, request): if referer_is_current(request): return getNavigationRoot(context) try: return request.getHeader('referer').replace( get_site_url(context), get_site_path(context)) except (AttributeError, TypeError): return None
def __call__(self): self.search_term = self.request.form.get('q', None) if not isinstance(self.search_term, unicode): self.search_term = self.search_term.decode('utf-8') self.limit = int(self.request.form.get('limit', 10)) self.path = self.request.form.get('path', getNavigationRoot(self.context)) results = self.results() return self.render_results(results)
def _path(context, row): values = row.values if not '/' in values: # It must be a UID values = '/'.join(getPathByUID(context, values)) # take care of absolute paths without nav_root nav_root = getNavigationRoot(context) if not values.startswith(nav_root): values = nav_root + values tmp = {row.index: {'query': values, }} return tmp
def _path(context, row): values = row.values if not "/" in values: # It must be a UID values = "/".join(getPathByUID(context, values)) # take care of absolute paths without nav_root nav_root = getNavigationRoot(context) if not values.startswith(nav_root): values = nav_root + values tmp = {row.index: {"query": values}} return tmp
def _relativePath(context, row): # Walk through the tree obj = context vals = list() navroot = getNavigationRoot(context) try: obj = context.restrictedTraverse(row.values[0]) vals.append('/'.join(obj.getPhysicalPath())) except Exception: vals.append('%s/%s' % (navroot, row.values[0])) row = Row(index=row.index, operator=row.operator, values=vals) return _path(context, row)
def _filter_query(self, query): request = self.request catalog = getToolByName(self.context, 'portal_catalog') valid_indexes = tuple(catalog.indexes()) valid_keys = self.valid_keys + valid_indexes text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') if not text: # Without text, must provide a meaningful non-empty search valid = set(valid_indexes).intersection(request.form.keys()) or \ set(valid_indexes).intersection(query.keys()) if not valid: return for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith('facet.')): query[k] = v if text: query['SearchableText'] = self.munge_search_term(text) # don't filter on created at all if we want all results created = query.get('created') if created: try: if created.get('query', EVER) <= EVER: del query['created'] except AttributeError: # created not a mapping del query['created'] # https://github.com/plone/Products.CMFPlone/issues/3007 # If 'created' exists and is of type 'record', then cast it as dict if 'created' in query and isinstance(query['created'], record): query['created'] = dict(query['created']) # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) if 'sort_order' in query and not query['sort_order']: del query['sort_order'] return query
def get_author_content(self, userId, path = None): catalog = getToolByName(self.context, 'portal_catalog') utils = getToolByName(self.context, 'plone_utils') friendly_types = utils.getUserFriendlyTypes() found = {} if path is None: path = getNavigationRoot(self.context) lencontent = len(catalog.searchResults(Creator = userId, portal_type = friendly_types, path = path)) - 1 if lencontent < 0: lencontent = 0; return lencontent
def __call__(self): context = aq_inner(self.context) q = self.request.form.get('term', None) self.limit = int(self.request.form.get('limit', 10)) path = self.request.form.get('path', None) plone_utils = getToolByName(context, 'plone_utils') self.pretty_title_or_id = plone_utils.pretty_title_or_id self.normalizeString = plone_utils.normalizeString plone_view = getMultiAdapter((context, self.request), name='plone') self.get_icon = plone_view.getIcon pprops = getToolByName(context, 'portal_properties') sprops = getattr(pprops, 'site_properties', None) self.useViewAction = [] if sprops is not None: self.useViewAction = sprops.getProperty('typesUseViewActionInListings', []) registry = getUtility(IRegistry) self.settings = registry.forInterface(ILiveSearchSettings) q = prepare_SearchableText(q) r = q + '*' self.searchterms = url_quote_plus(r) site_encoding = plone_utils.getSiteEncoding() if path is None: path = getNavigationRoot(context) catalog = getToolByName(context, 'portal_catalog') friendly_types = plone_utils.getUserFriendlyTypes() self.facet_params = context.restrictedTraverse( '@@search-facets/facet_parameters')() self.searchterm_query = '?searchterm=%s' % url_quote_plus(q) if self.settings.grouping: results = catalog(SearchableText=r, portal_type=friendly_types, request_handler='livesearch', path=path, sort_limit=self.settings.group_search_limit)[:self.settings.group_search_limit] else: results = catalog(SearchableText=r, portal_type=friendly_types, request_handler='livesearch', path=path, sort_limit=self.limit)[:self.limit] self.request.response.setHeader( 'Content-Type', 'application/json;charset=%s' % site_encoding) return self.get_results_as_json(results)
def _filter_query(self, query): """The _filter_query of the standard search view (plone.app.search) cancel the query generation if not SearchableText is given. In some case (for example in opengever.advancedsearch), we generate also searches without a searchabletext. So we temporarily fake the SearchableText. Besides that we also handle date range queries and subject queries separately. XXX This method should be removed, after the solr integration meta-XXX should it? now it contains custom stuff. """ request = self.request text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') for key, value in request.form.items(): self.handle_query_filter_value(query, key, value) if text: query['SearchableText'] = quote_chars(text) # don't filter on created at all if we want all results created = query.get('created') if created: if created.get('query'): if created['query'][0] <= EVER: del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) # Special treatment for the Subject index # The index only stores unicode values, so we have to search # for unicode values. if 'Subject' in query: query['Subject'] = safe_unicode(query['Subject']) return query
def filter_query(self, query): request = self.request catalog = getToolByName(self.context, "portal_catalog") valid_indexes = tuple(catalog.indexes()) valid_keys = self.valid_keys + valid_indexes text = query.get("SearchableText", None) if text is None: text = request.form.get("SearchableText", "") if not text: # Without text, must provide a meaningful non-empty search valid = set(valid_indexes).intersection(list( request.form.keys())) or set(valid_indexes).intersection( list(query.keys())) if not valid: return for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith("facet.")): query[k] = v if text: query["SearchableText"] = self.munge_search_term(text) # don't filter on created at all if we want all results created = query.get("created") if created: try: if created.get("query") and created["query"][0] <= EVER: del query["created"] except AttributeError: # created not a mapping del query["created"] # respect `types_not_searched` setting types = query.get("portal_type", []) if "query" in types: types = types["query"] query["portal_type"] = self.filter_types(types) # respect effective/expiration date query["show_inactive"] = False # respect navigation root if "path" not in query: query["path"] = getNavigationRoot(self.context) if "sort_order" in query and not query["sort_order"]: del query["sort_order"] return query
def filter_query(self, query): request = self.request catalog = getToolByName(self.context, "portal_catalog") valid_indexes = tuple(catalog.indexes()) valid_keys = self.valid_keys + valid_indexes text = query.get("SearchableText", None) if text is None: text = request.form.get("SearchableText", "") if not text: # Without text, must provide a meaningful non-empty search valid = set(valid_indexes).intersection(request.form.keys()) or set(valid_indexes).intersection( query.keys() ) if not valid: return for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith("facet.")): query[k] = v if text: query["SearchableText"] = self.munge_search_term(text) # don't filter on created at all if we want all results created = query.get("created") if created: try: if created.get("query") and created["query"][0] <= EVER: del query["created"] except AttributeError: # created not a mapping del query["created"] # respect `types_not_searched` setting types = query.get("portal_type", []) if "query" in types: types = types["query"] query["portal_type"] = self.filter_types(types) # respect effective/expiration date query["show_inactive"] = False # respect navigation root if "path" not in query: query["path"] = getNavigationRoot(self.context) if "sort_order" in query and not query["sort_order"]: del query["sort_order"] return query
def filter_query(self, query): request = self.request catalog = getToolByName(self.context, 'portal_catalog') valid_indexes = tuple(catalog.indexes()) valid_keys = self.valid_keys + valid_indexes text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') if not text: # Without text, must provide a meaningful non-empty search valid = set(valid_indexes).intersection(request.form.keys()) or \ set(valid_indexes).intersection(query.keys()) if not valid: return for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith('facet.')): query[k] = v if text: query['SearchableText'] = self.munge_search_term(text) # don't filter on created at all if we want all results created = query.get('created') if created: try: if created.get('query') and created['query'][0] <= EVER: del query['created'] except AttributeError: # created not a mapping del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) if 'sort_order' in query and not query['sort_order']: del query['sort_order'] return query
def filter_query(self, query): """The filter query of the standard search view (plone.app.search) cancel the query generation if not SearchableText is given. In some case (for example in opengever.advancedsearch), we generate also searches without a searchabletext. So we temporarily fake the SearchableText. XXX This method should be removed, after the solr integration""" request = self.request text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') catalog = getToolByName(self.context, 'portal_catalog') valid_keys = self.valid_keys + tuple(catalog.indexes()) for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith('facet.')) \ and not k.endswith('_usage'): if '%s_usage' % (k) in request.form.keys(): v = {'query': (DateTime(v[0]), DateTime(v[1])), 'range': 'min:max'} query[k] = v if text: query['SearchableText'] = quote_chars(text) # don't filter on created at all if we want all results created = query.get('created') if created: if created.get('query'): if created['query'][0] <= EVER: del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) return query
def filter_query(self, query): request = self.request catalog = getToolByName(self.context, 'portal_catalog') valid_indexes = tuple(catalog.indexes()) valid_keys = self.valid_keys + valid_indexes text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') if not text: # Without text, must provide a meaningful non-empty search valid = set(valid_indexes).intersection(request.form.keys()) or \ set(valid_indexes).intersection(query.keys()) if not valid: return for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith('facet.')): query[k] = v if text: query['SearchableText'] = quote_chars(text) # don't filter on created at all if we want all results created = query.get('created') if created: try: if created.get('query') and created['query'][0] <= EVER: del query['created'] except AttributeError: # created not a mapping del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) return query
def filter_query(self, query): registry = getUtility(IRegistry) search_settings = registry.forInterface(ISearchSchema, prefix="plone") types = query.get("portal_type", []) if "query" in types: types = types["query"] query["portal_type"] = self.filter_types(types) # respect effective/expiration date query["show_inactive"] = False # respect navigation root if "path" not in query: query["path"] = {"query": getNavigationRoot(self.context)} vhm_physical_path = self.request.get("VirtualRootPhysicalPath") # if vhm trick is applied, we should present a stripped path, as it will be # processed again in _constrain_query_by_path if vhm_physical_path: bits = query["path"]["query"].split( "/")[len(vhm_physical_path):] query["path"]["query"] = "/".join(bits) or "/" default_sort_on = search_settings.sort_on if "sort_on" not in query: if default_sort_on != "relevance": query["sort_on"] = self.default_sort_on elif query["sort_on"] == "relevance": del query["sort_on"] if not query.get("sort_order") and (query.get( "sort_on", "") == "Date" or query.get( "sort_on", "") == "effective" # compatibility with Volto ): query["sort_order"] = "reverse" elif "sort_order" in query: del query["sort_order"] if "sort_order" in query and not query["sort_order"]: del query["sort_order"] return query
def filter_query(self): """ Make some query filtering. """ request = self.request query = {} validation_messages = [] # text = request.form.get('SearchableText', '') valid_keys = self.valid_keys + tuple(self.catalog.indexes()) for k, v in request.form.items(): if k == 'SearchableText': v, text_validation = self.validateSearchableText(k, v) validation_messages.extend(text_validation) if v: query[k] = self.setFilteredIndex(k, v, valid_keys) if not query: validation_messages.append( translate( _( 'search_no_query_label', default=u'You need to pass some query value.', ), context=self.request, )) return query, validation_messages # don't filter on created at all if we want all results created = query.get('created') if created: if created.get('query'): if created['query'][0] <= EVER: del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) return query, validation_messages
def filter_query(self, query): request = self.request text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') if not text: # Without text, the only meaningful case is Subject subjects = request.form.get('Subject') if not subjects: return valid_keys = self.valid_keys for catalog_name in self.catalogs: catalog = getToolByName(self.context, catalog_name) valid_keys = valid_keys + tuple(catalog.indexes()) valid_keys = sorted(set(valid_keys)) for k, v in request.form.items(): if v and ((k in valid_keys) or k.startswith('facet.')): query[k] = v if text: query['SearchableText'] = quote_chars(text) # don't filter on created at all if we want all results created = query.get('created') if created: if created.get('query'): if created['query'][0] <= EVER: del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # respect effective/expiration date query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) return query
def my_stepbystep(self): """ Return all stepbystep where the current logged-in user is the responsible person. """ records = [] criteria = {} context = aq_inner(self.context) current_user = getCurrentUser(self) searchpath = getNavigationRoot(context) criteria['path'] = searchpath criteria['Type'] = 'Step' criteria['Creator'] = current_user brains = self.context.queryCatalog(criteria) for brain in brains: obj = brain.getObject() records.append(obj) return records
def __call__(self, *args, **kw): self.args = args self.kw = kw query = self.default_query.copy() form = self.request.form if self.queryparam in form: # filter out everything but our ddc attributes if self.queryparam == 'fq': form[self.queryparam] = [ x for x in form[self.queryparam] if x.split(':')[0].strip('+') in self.facet_fields] self.form = form query.update(self.form) if 'set_language' in query: del(query['set_language']) for key in query.keys(): if query[key] == '': del(query[key]) if form.get('use_navigation_root', True) and 'path' not in query: query['path'] = getNavigationRoot(self.context) catalog = getToolByName(self.context, 'portal_catalog') self.results = catalog(query) self.kw['results'] = self.results return super(BrowseTopicsView, self).__call__(*args, **kw)
def rootAtNavigationRoot(query): if 'path' not in query: query['path'] = getNavigationRoot(context)
def render(self): # We set the parameters sent in livesearch using the old way. q = self.request['q'] limit = 10 path = None ploneUtils = getToolByName(self.context, 'plone_utils') portal_url = getToolByName(self.context, 'portal_url')() pretty_title_or_id = ploneUtils.pretty_title_or_id portalProperties = getToolByName(self.context, 'portal_properties') siteProperties = getattr(portalProperties, 'site_properties', None) useViewAction = [] if siteProperties is not None: useViewAction = siteProperties.getProperty('typesUseViewActionInListings', []) # SIMPLE CONFIGURATION MAX_TITLE = 40 MAX_DESCRIPTION = 80 # generate a result set for the query catalog = self.context.portal_catalog friendly_types = ploneUtils.getUserFriendlyTypes() def quotestring(s): return '"%s"' % s def quote_bad_chars(s): bad_chars = ["(", ")"] for char in bad_chars: s = s.replace(char, quotestring(char)) return s multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = q.split() r = " AND ".join(r) r = quote_bad_chars(r) + '*' searchterms = url_quote_plus(r) params = {'SearchableText': r, 'portal_type': friendly_types, 'sort_limit': limit + 1} if path is None: # useful for subsides params['path'] = getNavigationRoot(self.context) else: params['path'] = path params["Language"] = pref_lang() # search limit+1 results to know if limit is exceeded results = catalog(**params) REQUEST = self.context.REQUEST RESPONSE = REQUEST.RESPONSE RESPONSE.setHeader('Content-Type', 'application/json') label_show_all = _('label_show_all', default='Show all items') ts = getToolByName(self.context, 'translation_service') queryElements = [] if results: # TODO: We have to build a JSON with the desired parameters. for result in results[:limit]: # Calculate icon replacing '.' per '-' as '.' in portal_types break CSS icon = result.portal_type.lower().replace(".", "-") itemUrl = result.getURL() if result.portal_type in useViewAction: itemUrl += '/view' full_title = safe_unicode(pretty_title_or_id(result)) if len(full_title) > MAX_TITLE: display_title = ''.join((full_title[:MAX_TITLE], '...')) else: display_title = full_title full_title = full_title.replace('"', '"') display_description = safe_unicode(result.Description) if len(display_description) > MAX_DESCRIPTION: display_description = ''.join( (display_description[:MAX_DESCRIPTION], '...')) # We build the dictionary element with the desired parameters and we add it to the queryElements array. queryElement = { 'class': '', 'title': display_title, 'description': display_description, 'itemUrl': itemUrl, 'icon': icon} queryElements.append(queryElement) return json.dumps(queryElements)
# See http://dev.plone.org/plone/ticket/9422 for an explanation of '\u3000' multispace = u"\u3000".encode("utf-8") for char in ("?", "-", "+", "*", multispace): q = q.replace(char, " ") r = q.split() r = " AND ".join(r) r = quote_bad_chars(r) + "*" searchterms = url_quote_plus(r) site_encoding = context.plone_utils.getSiteEncoding() params = {"SearchableText": r, "portal_type": friendly_types, "sort_limit": limit + 1} if path is None: # useful for subsides params["path"] = getNavigationRoot(context) else: params["path"] = path # search limit+1 results to know if limit is exceeded results = catalog(**params) searchterm_query = "?searchterm=%s" % url_quote_plus(q) REQUEST = context.REQUEST RESPONSE = REQUEST.RESPONSE RESPONSE.setHeader("Content-Type", "text/xml;charset=%s" % site_encoding) # replace named entities with their numbered counterparts, in the xml the named ones are not correct # ↓ --> ↓ # … --> …
def base_filter_query(self, query): # based on filter_query, but with substantial difference so not # subclassing the original method. request = self.request rawtext = text = query.get('SearchableText', None) if text is None: text = request.form.get('SearchableText', '') if not text: # Without text, the only meaningful case is Subject subjects = request.form.get('Subject') if not subjects: return else: rawtext = text = text.strip() if '*' not in text: text += '*' # Stuff text into all PMR2/CellML/Cmeta indexes. cmeta_indexes = ( 'pmr2_authors_family_name', # XXX ^ this will become # 'cmeta_authors_family_name', 'cmeta_citation_title_keyword', 'cmeta_citation_publication_year', ) if rawtext: searchkeys = rawtext.lower().split() for i in cmeta_indexes: query[i] = searchkeys # XXX this should be configurable query['pmr2_review_state'] = ['published'] catalog = getToolByName(self.context, 'portal_catalog') # AdvancedQuery does not understand these other keywords # valid_keys = self.valid_keys + tuple(catalog.indexes()) valid_keys = tuple(catalog.indexes()) for k, v in request.form.items(): # XXX not sure what facet is, aside from a deprecated # product. # if v and ((k in valid_keys) or k.startswith('facet.')): if v and (k in valid_keys): query[k] = v if text: query['SearchableText'] = quote_chars(text) # don't filter on created at all if we want all results created = query.get('created') if created: if created.get('query'): if created['query'][0] <= EVER: del query['created'] # respect `types_not_searched` setting types = query.get('portal_type', []) if 'query' in types: types = types['query'] query['portal_type'] = self.filter_types(types) # # respect effective/expiration date # query['show_inactive'] = False # respect navigation root if 'path' not in query: query['path'] = getNavigationRoot(self.context) return query
# See http://dev.plone.org/plone/ticket/9422 for an explanation of '\u3000' multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = q.split() r = " AND ".join(r) r = quote_bad_chars(r) + '*' searchterms = url_quote_plus(r) params = {'SearchableText': r, 'portal_type': friendly_types, 'sort_limit': limit + 1} if path is None: # useful for subsides params['path'] = getNavigationRoot(context) else: params['path'] = path # search limit+1 results to know if limit is exceeded results = catalog(**params) searchterm_query = '?searchterm=%s' % url_quote_plus(q) REQUEST = context.REQUEST RESPONSE = REQUEST.RESPONSE RESPONSE.setHeader('Content-Type', 'text/xml;charset=utf-8') # replace named entities with their numbered counterparts, in the xml the named # ones are not correct # ↓ --> ↓
def __call__(self): context = aq_inner(self.context) q = self.request.form.get('q', None) self.limit = int(self.request.form.get('limit', 10)) path = self.request.form.get('path', None) plone_utils = getToolByName(context, 'plone_utils') self.pretty_title_or_id = plone_utils.pretty_title_or_id self.normalizeString = plone_utils.normalizeString plone_view = getMultiAdapter((context, self.request), name='plone') self.getIcon = plone_view.getIcon pprops = getToolByName(context, 'portal_properties') sprops = getattr(pprops, 'site_properties', None) self.useViewAction = [] if sprops is not None: self.useViewAction = sprops.getProperty( 'typesUseViewActionInListings', []) registry = getUtility(IRegistry) self.settings = registry.forInterface(ILiveSearchSettings) # XXX really if it contains + * ? or - # it will not be right since the catalog ignores all non-word # characters equally like # so we don't even attept to make that right. # But we strip these and these so that the catalog does # not interpret them as metachars # See http://dev.plone.org/plone/ticket/9422 for an explanation of '\u3000' multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = quote_bad_chars(q) + '*' self.searchterms = url_quote_plus(r) site_encoding = plone_utils.getSiteEncoding() if path is None: path = getNavigationRoot(context) catalog = getToolByName(context, 'portal_catalog') friendly_types = plone_utils.getUserFriendlyTypes() self.facet_params = context.restrictedTraverse( '@@search-facets/facet_parameters')() if self.settings.grouping: results = catalog(SearchableText=r, portal_type=friendly_types, qt='livesearch', path=path, sort_limit=self.settings.group_search_limit) group_by_types = self.settings.group_by + ['other'] grouped_results = {} for type_ in group_by_types: grouped_results[type_] = [] for result in results[:self.settings.group_search_limit]: if result.portal_type in grouped_results: grouped_results[result.portal_type].append(result) else: grouped_results['other'].append(result) else: results = catalog(SearchableText=r, portal_type=friendly_types, qt='livesearch', path=path, sort_limit=self.limit) self.searchterm_query = '?searchterm=%s' % url_quote_plus(q) if not results: self.write('''<fieldset class="livesearchContainer">''') self.write('''<legend id="livesearchLegend">%s</legend>''' % (translate(legend_livesearch, context=self.request))) self.write('''<div class="LSIEFix">''') self.write( '''<div id="LSNothingFound">%s</div>''' % (translate(label_no_results_found, context=self.request))) self.write('''</div>''') self.write('''</fieldset>''') else: self.write('''<fieldset class="livesearchContainer">''') self.write('''<legend id="livesearchLegend">%s</legend>''' % (translate(legend_livesearch, context=self.request))) self.write('''<div class="LSIEFix">''') if self.settings.grouping: self.write_grouped_results(grouped_results, group_by_types) else: self.write_results(results) self.write('''</div>''') self.write('''</fieldset>''') self.request.response.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding) return '\n'.join(self.output).encode(site_encoding)
# characters equally like # so we don't even attept to make that right. # But we strip these and these so that the catalog does # not interpret them as metachars # See http://dev.plone.org/plone/ticket/9422 for an explanation of '\u3000' multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = q.split() r = " AND ".join(r) r = quote_bad_chars(r)+'*' searchterms = url_quote_plus(r) site_encoding = context.plone_utils.getSiteEncoding() if path is None: path = getNavigationRoot(context) results = catalog(SearchableText=r, portal_type=friendly_types, path=path, sort_limit=limit) searchterm_query = '?searchterm=%s'%url_quote_plus(q) REQUEST = context.REQUEST RESPONSE = REQUEST.RESPONSE RESPONSE.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding) # replace named entities with their numbered counterparts, in the xml the named ones are not correct # ↓ --> ↓ # … --> … legend_livesearch = _('legend_livesearch', default='LiveSearch ↓') label_no_results_found = _('label_no_results_found', default='No matching results found.') label_advanced_search = _('label_advanced_search', default='Advanced Search…')
def render(self): # We set the parameters sent in livesearch using the old way. q = self.request['q'] limit = 10 path = None ploneUtils = getToolByName(self.context, 'plone_utils') portal_url = getToolByName(self.context, 'portal_url')() pretty_title_or_id = ploneUtils.pretty_title_or_id portalProperties = getToolByName(self.context, 'portal_properties') siteProperties = getattr(portalProperties, 'site_properties', None) useViewAction = [] if siteProperties is not None: useViewAction = siteProperties.getProperty('typesUseViewActionInListings', []) # SIMPLE CONFIGURATION MAX_TITLE = 40 MAX_DESCRIPTION = 80 # generate a result set for the query catalog = self.context.portal_catalog friendly_types = ploneUtils.getUserFriendlyTypes() def quotestring(s): return '"%s"' % s def quote_bad_chars(s): bad_chars = ["(", ")"] for char in bad_chars: s = s.replace(char, quotestring(char)) return s multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = q.split() r = " AND ".join(r) r = quote_bad_chars(r) + '*' searchterms = url_quote_plus(r) params = {'SearchableText': r, 'portal_type': friendly_types, 'sort_limit': limit + 1} if path is None: # useful for subsides params['path'] = getNavigationRoot(self.context) else: params['path'] = path # search limit+1 results to know if limit is exceeded results = catalog(**params) searchterm_query = '?searchterm=%s' % url_quote_plus(q) REQUEST = self.context.REQUEST RESPONSE = REQUEST.RESPONSE RESPONSE.setHeader('Content-Type', 'application/json') label_no_results_found = _('label_no_results_found', default='No matching results found.') label_advanced_search = _('label_advanced_search', default='Advanced Search…') label_show_all = _('label_show_all', default='Show all items') ts = getToolByName(self.context, 'translation_service') queryElements = [] if results: # TODO: We have to build a JSON with the desired parameters. for result in results[:limit]: # Calculate icon replacing '.' per '-' as '.' in portal_types break CSS icon = result.portal_type.lower().replace(".", "-") itemUrl = result.getURL() if result.portal_type in useViewAction: itemUrl += '/view' itemUrl = itemUrl + searchterm_query full_title = safe_unicode(pretty_title_or_id(result)) if len(full_title) > MAX_TITLE: display_title = ''.join((full_title[:MAX_TITLE], '...')) else: display_title = full_title full_title = full_title.replace('"', '"') display_description = safe_unicode(result.Description) if len(display_description) > MAX_DESCRIPTION: display_description = ''.join( (display_description[:MAX_DESCRIPTION], '...')) # We build the dictionary element with the desired parameters and we add it to the queryElements array. queryElement = {'title': display_title, 'description': display_description, 'itemUrl': itemUrl, 'icon': icon} queryElements.append(queryElement) if len(results) > limit: #We have to add here an element to the JSON in case there is too many elements. searchquery = '/@@search?SearchableText=%s&path=%s' \ % (searchterms, params['path']) too_many_results = {'title': ts.translate(label_show_all, context=REQUEST), 'description': '', 'itemUrl': portal_url + searchquery, 'icon': ''} queryElements.append(too_many_results) else: # No results no_results = {'title': ts.translate(label_no_results_found, context=REQUEST), 'description': '', 'itemUrl': portal_url + '/@@search', 'icon': ''} queryElements.append(no_results) advancedSearch = {'title': ts.translate(label_advanced_search, context=REQUEST), 'description': '', 'itemUrl': portal_url + '/@@search', 'icon': ''} queryElements.append(advancedSearch) return json.dumps(queryElements)
for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = q.split() r = " AND ".join(r) r = quote_bad_chars(r) + '*' searchterms = url_quote_plus(r) REQUEST = context.REQUEST params = {'SearchableText': r, 'sort_limit': limit + 1} if 'portal_type' not in REQUEST: params['portal_type'] = friendly_types if path is None: # useful for subsides params['path'] = getNavigationRoot(context) else: params['path'] = path # search limit+1 results to know if limit is exceeded results = catalog(REQUEST, **params) searchterm_query = '?searchterm=%s' % url_quote_plus(q) RESPONSE = REQUEST.RESPONSE RESPONSE.setHeader('Content-Type', 'text/xml;charset=utf-8') # replace named entities with their numbered counterparts, in the xml the named # ones are not correct # ↓ --> ↓ # … --> …
def __call__(self): context = aq_inner(self.context) q = self.request.form.get('q', None) self.limit = int(self.request.form.get('limit', 10)) path = self.request.form.get('path', None) plone_utils = getToolByName(context, 'plone_utils') self.pretty_title_or_id = plone_utils.pretty_title_or_id self.normalizeString = plone_utils.normalizeString plone_view = getMultiAdapter((context, self.request), name='plone') self.getIcon = plone_view.getIcon pprops = getToolByName(context, 'portal_properties') sprops = getattr(pprops, 'site_properties', None) self.useViewAction = [] if sprops is not None: self.useViewAction = sprops.getProperty('typesUseViewActionInListings', []) registry = getUtility(IRegistry) self.settings = registry.forInterface(ILiveSearchSettings) # XXX really if it contains + * ? or - # it will not be right since the catalog ignores all non-word # characters equally like # so we don't even attept to make that right. # But we strip these and these so that the catalog does # not interpret them as metachars # See http://dev.plone.org/plone/ticket/9422 for an explanation of '\u3000' multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = quote_bad_chars(q)+'*' self.searchterms = url_quote_plus(r) site_encoding = plone_utils.getSiteEncoding() if path is None: path = getNavigationRoot(context) catalog = getToolByName(context, 'portal_catalog') friendly_types = plone_utils.getUserFriendlyTypes() self.facet_params = context.restrictedTraverse('@@search-facets/facet_parameters')() if self.settings.grouping: results = catalog(SearchableText=r, portal_type=friendly_types, qt='livesearch', path=path, sort_limit=self.settings.group_search_limit) group_by_types = self.settings.group_by + ['other'] grouped_results = {} for type_ in group_by_types: grouped_results[type_] = [] for result in results[:self.settings.group_search_limit]: if result.portal_type in grouped_results: grouped_results[result.portal_type].append(result) else: grouped_results['other'].append(result) else: results = catalog(SearchableText=r, portal_type=friendly_types, qt='livesearch', path=path, sort_limit=self.limit) self.searchterm_query = '?searchterm=%s'%url_quote_plus(q) if not results: self.write('''<fieldset class="livesearchContainer">''') self.write('''<legend id="livesearchLegend">%s</legend>''' % ( translate(legend_livesearch, context=self.request))) self.write('''<div class="LSIEFix">''') self.write('''<div id="LSNothingFound">%s</div>''' % ( translate(label_no_results_found, context=self.request))) self.write('''</div>''') self.write('''</fieldset>''') else: self.write('''<fieldset class="livesearchContainer">''') self.write('''<legend id="livesearchLegend">%s</legend>''' % ( translate(legend_livesearch, context=self.request))) self.write('''<div class="LSIEFix">''') if self.settings.grouping: self.write_grouped_results(grouped_results, group_by_types) else: self.write_results(results) self.write('''</div>''') self.write('''</fieldset>''') self.request.response.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding) return '\n'.join(self.output).encode(site_encoding)
## Script (Python) "getLatestCalendarX" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters= ##title=return the latest published Season as a brain ## from DateTime.DateTime import DateTime from Products.CMFCore.utils import getToolByName from Products.CMFPlone.browser.navtree import getNavigationRoot catalog = getToolByName(context, 'portal_catalog') limit = 1 state = 'published' path = getNavigationRoot(context) brain = None brains = catalog(portal_type='CalendarXFolder', review_state=state, effective={'query': DateTime(), 'range': 'max'}, path=path, sort_on='effective', sort_order='descending', sort_limit=limit)[:limit] if brains: brain = brains[0] return brain
def rootAtNavigationRoot(query): if "path" not in query: query["path"] = getNavigationRoot(context)
def result(self): context = self.context request = self.request response = self.request.response q = request.get('q') limit = int(request.get('limit', 10)) path = request.get('path', None) ploneUtils = getToolByName(context, 'plone_utils') portal_url = getToolByName(context, 'portal_url')() pretty_title_or_id = ploneUtils.pretty_title_or_id portalProperties = getToolByName(context, 'portal_properties') siteProperties = getattr(portalProperties, 'site_properties', None) useViewAction = [] if siteProperties is not None: useViewAction = siteProperties.getProperty('typesUseViewActionInListings', []) # SIMPLE CONFIGURATION MAX_TITLE = 29 MAX_DESCRIPTION = 93 mtool = getToolByName(context, 'portal_membership') friendly_types = ploneUtils.getUserFriendlyTypes() def quotestring(s): return '"%s"' % s def quote_bad_chars(s): bad_chars = ["(", ")"] for char in bad_chars: s = s.replace(char, quotestring(char)) return s def pretty_date(when): result = ('%s %s, %s') % (DateTime(when).strftime('%B'), DateTime(when).strftime('%d'), DateTime(when).strftime('%Y')) return result multispace = u'\u3000'.encode('utf-8') for char in ('?', '-', '+', '*', multispace): q = q.replace(char, ' ') r = q.split() r = " AND ".join(r) r = quote_bad_chars(r) + '*' searchterms = url_quote_plus(r) site_encoding = context.plone_utils.getSiteEncoding() params = {'SearchableText': r, 'portal_type': friendly_types, 'sort_limit': limit + 1} if path is None: # useful for subsides params['path'] = getNavigationRoot(context) else: params['path'] = path # search limit+1 results to know if limit is exceeded #params = get_query(searchable_text, params) #results = catalog(**params) results = query(params) searchterm_query = '?searchterm=%s' % url_quote_plus(q) #request = context.request #response = request.response response.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding) # replace named entities with their numbered counterparts, in the xml the named ones are not correct # ↓ --> ↓ # … --> … legend_livesearch = _('legend_livesearch', default='LiveSearch ↓') label_no_results_found = _('label_no_results_found', default='No matching results found.') label_advanced_search = _('label_advanced_search', default='Advanced Search…') label_show_all = _('label_show_all', default='Show all items') ts = getToolByName(context, 'translation_service') output = [] def write(s): output.append(safe_unicode(s)) if not results: write('''<fieldset class="livesearchContainer">''') write('''<legend id="livesearchLegend">%s</legend>''' % ts.translate(legend_livesearch, context=request)) write('''<div class="LSIEFix">''') write('''<div id="LSNothingFound">%s</div>''' % ts.translate(label_no_results_found, context=request)) write('''<ul class="ls-foot">''') write('''<li class="LSRow lsrow-adv-search">''') write('<b></b><a href="%s" style="font-weight:normal">%s</a>' % (portal_url + '/@@search', ts.translate(label_advanced_search, context=request))) write('''</li>''') write('''</ul>''') write('''</div>''') write('''</fieldset>''') else: write('''<fieldset class="livesearchContainer">''') write('''<legend id="livesearchLegend">%s</legend>''' % ts.translate(legend_livesearch, context=request)) write('''<div class="LSIEFix">''') write('''<ul class="LSTable">''') for result in results[:limit]: # breadcrumbs obj = result.getObject() breadcrumbs_view = getMultiAdapter((obj, request), name='breadcrumbs_view') breadcrumbs = breadcrumbs_view.breadcrumbs() ls_breadcrumb = '' breadcrumbs_size = len(breadcrumbs) - 1 if breadcrumbs_size > 0: for ls_key in breadcrumbs[:breadcrumbs_size]: ls_breadcrumb += ('''<a href="%s">%s</a> > ''' % (ls_key['absolute_url'], ls_key['Title'])) is_folderish = result.is_folderish if is_folderish: length_size = len(obj) else: length_size = result.getObjSize #icon = plone_view.getIcon(result) img_class = '%s-icon' % ploneUtils.normalizeString(result.portal_type) member = mtool.getMemberById(result.Creator) if member is not None: fullname = member.getProperty('fullname') else: fullname = '' itemUrl = result.getURL() if result.portal_type in useViewAction: itemUrl += '/view' itemUrl = itemUrl + searchterm_query write('''<li class="LSRow">''') #write(icon.html_tag() or '') write('''<div class="%s ls-content-icon"></div>''' % (img_class)) write('''<div class="ls-details">''') full_title = safe_unicode(pretty_title_or_id(result)) if len(full_title) > MAX_TITLE: display_title = ''.join((full_title[:MAX_TITLE], '...')) else: display_title = full_title full_title = full_title.replace('"', '"') #klass = 'contenttype-%s' % ploneUtils.normalizeString(result.portal_type) klass = 'ls-content-title' write('''<a href="%s" title="%s" class="%s">%s</a>''' % (itemUrl, full_title, klass, display_title)) display_description = safe_unicode(result.Description) if len(display_description) > MAX_DESCRIPTION: display_description = ''.join((display_description[:MAX_DESCRIPTION], '...')) # need to quote it, to avoid injection of html containing javascript and other evil stuff display_description = html_quote(display_description) write('''<div class="LSDescr">%s</div>''' % (display_description)) if breadcrumbs_size > 0: write('''<div class="LSBreadcrumb">in %s</div>''' % (ls_breadcrumb[:-3])) else: write('''<div class="LSBreadcrumb">in Home</div>''') write('''<div class="LSMeta">''') display_type = html_quote(safe_unicode(result.Type)) write('''<span class="LSType">%s</span>''' % (display_type)) if result.Type == 'File' or result.Type == 'Image': write('''<span class="LSType"> • %s</span>''' % (length_size)) elif result.Type == 'Folder': write('''<span class="LSType"> • %s item(s)</span>''' % (length_size)) display_creator = html_quote(safe_unicode(fullname)) if len(display_creator) > 0: write(''' • Create by <a href="%s/author/%s" class="LSCreator">%s</a>''' % (portal_url, member.getProperty('id'), display_creator)) display_modified = html_quote(safe_unicode((pretty_date(result.modified)))) write('''<span class="LSModified">on %s</span>''' % (display_modified)) write('''</div>''') write('''</div>''') write('''</li>''') full_title, display_title, display_description, display_type = None, None, None, None write('''</ul><ul class="ls-foot">''') if len(results) > limit: # add a more... row write('''<li class="LSRow lsrow-show-all">''') searchquery = '@@search?SearchableText=%s&path=%s' % (searchterms, params['path']) write('<b></b><a href="%s" style="font-weight:normal">%s</a>' % ( searchquery, ts.translate(label_show_all, context=request))) write('''</li>''') write('''<li class="LSRow lsrow-adv-search">''') write('<b></b><a href="%s" style="font-weight:normal">%s</a>' % (portal_url + '/@@search', ts.translate(label_advanced_search, context=request))) write('''</li>''') write('''</ul>''') write('''</div>''') write('''</fieldset>''') return '\n'.join(output).encode(site_encoding)