def _findDevices(self, identifier, ipAddress, limit=None): """ Returns a tuple ([device brains], [devices]) searching manage IP and interface IPs. limit is the maximum total number in both lists. """ dev_cat = IModelCatalogTool(self._devices) try: ip_address = next(i for i in (ipAddress, identifier) if isip(i)) ip_decimal = ipToDecimal(ip_address) except Exception: ip_address = None ip_decimal = None quoted_id = quote_and_escape(identifier) query_set = Or(Eq('id', quoted_id), Eq('name', quoted_id)) if ip_decimal is not None: query_set.addSubquery(Eq('decimal_ipAddress', str(ip_decimal))) device_brains = list( dev_cat.search(types=Device, query=query_set, limit=limit, filterPermissions=False, fields=["uid", "uuid"])) if device_brains: return device_brains, [] if ip_decimal is not None: # don't search interfaces for 127.x.x.x IPv4 addresses if ipToDecimal('126.255.255.255') < ip_decimal < ipToDecimal( '128.0.0.0'): ip_decimal = None # don't search interfaces for the ::1 IPv6 address elif ipToDecimal('::1') == ip_decimal: ip_decimal = None if ip_decimal is None: return [], [] net_cat = IModelCatalogTool(self._networks) results = net_cat.search(types=IpAddress, query=(Eq('name', ip_address)), limit=limit, filterPermissions=False) devices = [brain.getObject().device() for brain in results] return device_brains, devices
def _findDevices(self, identifier, ipAddress, limit=None): """ Returns a tuple ([device brains], [devices]) searching manage IP and interface IPs. limit is the maximum total number in both lists. """ dev_cat = IModelCatalogTool(self._devices) try: ip_address = next(i for i in (ipAddress, identifier) if isip(i)) ip_decimal = ipToDecimal(ip_address) except Exception: ip_address = None ip_decimal = None quoted_id = quote_and_escape(identifier) query_set = Or(Eq('id', quoted_id), Eq('name', quoted_id)) if ip_decimal is not None: query_set.addSubquery(Eq('decimal_ipAddress', str(ip_decimal))) device_brains = list(dev_cat.search(types=Device, query=query_set, limit=limit, filterPermissions=False, fields=["uid", "uuid"])) if device_brains: return device_brains, [] if ip_decimal is not None: # don't search interfaces for 127.x.x.x IPv4 addresses if ipToDecimal('126.255.255.255') < ip_decimal < ipToDecimal('128.0.0.0'): ip_decimal = None # don't search interfaces for the ::1 IPv6 address elif ipToDecimal('::1') == ip_decimal: ip_decimal = None if ip_decimal is None: return [], [] net_cat = IModelCatalogTool(self._networks) results = net_cat.search(types=IpAddress, query=(Eq('name', ip_address)), limit = limit, filterPermissions = False) devices = [brain.getObject().device() for brain in results] return device_brains, devices
def __call__(self, result=None, specification=None, **kwargs): searchTerm = _c(self.request.get('searchTerm', '')).lower() force_all = self.request.get('force_all', 'false') searchFields = 'search_fields' in self.request \ and json.loads(_u(self.request.get('search_fields', '[]'))) \ or ('Title',) # lookup objects from ZODB catalog_name = _c(self.request.get('catalog_name', 'portal_catalog')) catalog = getToolByName(self.context, catalog_name) # json.loads does unicode conversion, which will fail in the catalog # search for some cases. So we need to convert the strings to utf8 # see: https://github.com/senaite/bika.lims/issues/443 base_query = json.loads(self.request['base_query']) search_query = json.loads(self.request.get('search_query', "{}")) base_query = self.to_utf8(base_query) search_query = self.to_utf8(search_query) # first with all queries contentFilter = dict((k, v) for k, v in base_query.items()) contentFilter.update(search_query) # Sorted by? (by default, Title) sort_on = self.request.get('sidx', 'Title') if sort_on == 'Title': sort_on = 'sortable_title' if sort_on: # Check if is an index and if is sortable. Otherwise, assume the # sorting must be done manually index = catalog.Indexes.get(sort_on, None) if index and index.meta_type in ['FieldIndex', 'DateIndex']: contentFilter['sort_on'] = sort_on # Sort order? sort_order = self.request.get('sord', 'asc') if (sort_order in ['desc', 'reverse', 'rev', 'descending']): contentFilter['sort_order'] = 'descending' else: contentFilter['sort_order'] = 'ascending' # Can do a search for indexes? criterias = [] fields_wo_index = [] if searchTerm: for field_name in searchFields: index = catalog.Indexes.get(field_name, None) if not index: fields_wo_index.append(field_name) continue if index.meta_type in ('ZCTextIndex'): if searchTerm.isspace(): # earchTerm != ' ' added because of # https://github.com/plone/Products.CMFPlone/issues # /1537 searchTerm = '' continue else: temp_st = searchTerm + '*' criterias.append(MatchRegexp(field_name, temp_st)) elif index.meta_type in ('FieldIndex'): criterias.append(MatchRegexp(field_name, searchTerm)) elif index.meta_type == 'DateIndex': msg = "Unhandled DateIndex search on '%s'" % field_name from bika.lims import logger logger.warn(msg) else: criterias.append(Generic(field_name, searchTerm)) if criterias: # Advanced search advanced_query = catalog.makeAdvancedQuery(contentFilter) aq_or = Or() for criteria in criterias: aq_or.addSubquery(criteria) advanced_query &= aq_or brains = catalog.evalAdvancedQuery(advanced_query) else: brains = catalog(contentFilter) if brains and searchTerm and fields_wo_index: _brains = [] for brain in brains: for field_name in fields_wo_index: value = getattr(brain, field_name, None) if not value: instance = brain.getObject() schema = instance.Schema() if field_name in schema: value = schema[field_name].get(instance) if callable(value): value = value() if value and value.lower().find(searchTerm) > -1: _brains.append(brain) break brains = _brains # Then just base_query alone ("show all if no match") if not brains and force_all.lower() == 'true': if search_query: brains = catalog(base_query) if brains and searchTerm: _brains = [ p for p in brains if p.Title.lower().find(searchTerm) > -1 ] if _brains: brains = _brains return brains
def folderitems(self, full_objects = False): """ >>> portal = layer['portal'] >>> portal_url = portal.absolute_url() >>> from plone.app.testing import SITE_OWNER_NAME >>> from plone.app.testing import SITE_OWNER_PASSWORD Test page batching https://github.com/bikalabs/Bika-LIMS/issues/1276 When visiting the second page, the Water sampletype should be displayed: >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD) >>> browser.open(portal_url+"/bika_setup/bika_sampletypes/folder_view?", ... "list_pagesize=10&list_review_state=default&list_pagenumber=2") >>> browser.contents '...Water...' """ #self.contentsMethod = self.context.getFolderContents if not hasattr(self, 'contentsMethod'): self.contentsMethod = getToolByName(self.context, self.catalog) context = aq_inner(self.context) plone_layout = getMultiAdapter((context, self.request), name = u'plone_layout') plone_utils = getToolByName(context, 'plone_utils') plone_view = getMultiAdapter((context, self.request), name = u'plone') portal_properties = getToolByName(context, 'portal_properties') portal_types = getToolByName(context, 'portal_types') workflow = getToolByName(context, 'portal_workflow') site_properties = portal_properties.site_properties norm = getUtility(IIDNormalizer).normalize if self.request.get('show_all', '').lower() == 'true' \ or self.show_all == True \ or self.pagesize == 0: show_all = True else: show_all = False pagenumber = int(self.request.get('pagenumber', 1) or 1) pagesize = self.pagesize start = (pagenumber - 1) * pagesize end = start + pagesize - 1 if (hasattr(self, 'And') and self.And) \ or (hasattr(self, 'Or') and self.Or): # if contentsMethod is capable, we do an AdvancedQuery. if hasattr(self.contentsMethod, 'makeAdvancedQuery'): aq = self.contentsMethod.makeAdvancedQuery(self.contentFilter) if hasattr(self, 'And') and self.And: tmpAnd = And() for q in self.And: tmpAnd.addSubquery(q) aq &= tmpAnd if hasattr(self, 'Or') and self.Or: tmpOr = Or() for q in self.Or: tmpOr.addSubquery(q) aq &= tmpOr brains = self.contentsMethod.evalAdvancedQuery(aq) else: # otherwise, self.contentsMethod must handle contentFilter brains = self.contentsMethod(self.contentFilter) else: brains = self.contentsMethod(self.contentFilter) results = [] self.page_start_index = 0 current_index = -1 for i, obj in enumerate(brains): # we don't know yet if it's a brain or an object path = hasattr(obj, 'getPath') and obj.getPath() or \ "/".join(obj.getPhysicalPath()) if hasattr(obj, 'getObject'): obj = obj.getObject() # check if the item must be rendered or not (prevents from # doing it later in folderitems) and dealing with paging if not self.isItemAllowed(obj): continue # avoid creating unnecessary info for items outside the current # batch; only the path is needed for the "select all" case... # we only take allowed items into account current_index += 1 if not show_all and not (start <= current_index <= end): results.append(dict(path = path, uid = obj.UID())) continue uid = obj.UID() title = obj.Title() description = obj.Description() icon = plone_layout.getIcon(obj) url = obj.absolute_url() relative_url = obj.absolute_url(relative = True) fti = portal_types.get(obj.portal_type) if fti is not None: type_title_msgid = fti.Title() else: type_title_msgid = obj.portal_type url_href_title = '%s at %s: %s' % ( t(type_title_msgid), path, to_utf8(description)) modified = self.ulocalized_time(obj.modified()), # element css classes type_class = 'contenttype-' + \ plone_utils.normalizeString(obj.portal_type) state_class = '' states = {} for w in workflow.getWorkflowsFor(obj): state = w._getWorkflowStateOf(obj).id states[w.state_var] = state state_class += "state-%s " % state results_dict = dict( obj = obj, id = obj.getId(), title = title, uid = uid, path = path, url = url, fti = fti, item_data = json.dumps([]), url_href_title = url_href_title, obj_type = obj.Type, size = obj.getObjSize, modified = modified, icon = icon.html_tag(), type_class = type_class, # a list of lookups for single-value-select fields choices = {}, state_class = state_class, relative_url = relative_url, view_url = url, table_row_class = "", category = 'None', # a list of names of fields that may be edited on this item allow_edit = [], # a list of names of fields that are compulsory (if editable) required = [], # "before", "after" and replace: dictionary (key is column ID) # A snippet of HTML which will be rendered # before/after/instead of the table cell content. before = {}, # { before : "<a href=..>" } after = {}, replace = {}, ) try: self.review_state = workflow.getInfoFor(obj, 'review_state') state_title = workflow.getTitleForStateOnType( self.review_state, obj.portal_type) state_title = t(PMF(state_title)) except: self.review_state = 'active' state_title = None if self.review_state: results_dict['review_state'] = self.review_state for state_var, state in states.items(): if not state_title: state_title = workflow.getTitleForStateOnType( state, obj.portal_type) results_dict[state_var] = state results_dict['state_title'] = state_title # extra classes for individual fields on this item { field_id : "css classes" } results_dict['class'] = {} for name, adapter in getAdapters((obj, ), IFieldIcons): auid = obj.UID() if hasattr(obj, 'UID') and callable(obj.UID) else None if not auid: continue alerts = adapter() # logger.info(str(alerts)) if alerts and auid in alerts: if auid in self.field_icons: self.field_icons[auid].extend(alerts[auid]) else: self.field_icons[auid] = alerts[auid] # Search for values for all columns in obj for key in self.columns.keys(): if hasattr(obj, key): # if the key is already in the results dict # then we don't replace it's value if results_dict.has_key(key): continue value = getattr(obj, key) if callable(value): value = value() results_dict[key] = value results.append(results_dict) return results
def folderitems(self, full_objects = False): """ """ #self.contentsMethod = self.context.getFolderContents if not hasattr(self, 'contentsMethod'): self.contentsMethod = getToolByName(self.context, self.catalog) context = aq_inner(self.context) plone_layout = getMultiAdapter((context, self.request), name = u'plone_layout') plone_utils = getToolByName(context, 'plone_utils') plone_view = getMultiAdapter((context, self.request), name = u'plone') portal_properties = getToolByName(context, 'portal_properties') portal_types = getToolByName(context, 'portal_types') workflow = getToolByName(context, 'portal_workflow') site_properties = portal_properties.site_properties norm = getUtility(IIDNormalizer).normalize show_all = self.request.get('show_all', '').lower() == 'true' pagenumber = int(self.request.get('pagenumber', 1) or 1) pagesize = self.pagesize start = (pagenumber - 1) * pagesize end = start + pagesize if (hasattr(self, 'And') and self.And) \ or (hasattr(self, 'Or') and self.Or): # if contentsMethod is capable, we do an AdvancedQuery. if hasattr(self.contentsMethod, 'makeAdvancedQuery'): aq = self.contentsMethod.makeAdvancedQuery(self.contentFilter) if hasattr(self, 'And') and self.And: tmpAnd = And() for q in self.And: tmpAnd.addSubquery(q) aq &= tmpAnd if hasattr(self, 'Or') and self.Or: tmpOr = Or() for q in self.Or: tmpOr.addSubquery(q) aq &= tmpOr brains = self.contentsMethod.evalAdvancedQuery(aq) else: # otherwise, self.contentsMethod must handle contentFilter brains = self.contentsMethod(self.contentFilter) else: brains = self.contentsMethod(self.contentFilter) results = [] self.page_start_index = "" for i, obj in enumerate(brains): # we don't know yet if it's a brain or an object path = hasattr(obj, 'getPath') and obj.getPath() or \ "/".join(obj.getPhysicalPath()) # avoid creating unnecessary info for items outside the current # batch; only the path is needed for the "select all" case... if not show_all and not start <= i < end: if hasattr(obj, 'getObject'): uid = obj.UID else: uid = obj.UID() results.append(dict(path = path, uid = uid)) continue if self.page_start_index == "": self.page_start_index = i if hasattr(obj, 'getObject'): obj = obj.getObject() uid = obj.UID() title = obj.Title() description = obj.Description() icon = plone_layout.getIcon(obj) url = obj.absolute_url() relative_url = obj.absolute_url(relative = True) fti = portal_types.get(obj.portal_type) if fti is not None: type_title_msgid = fti.Title() else: type_title_msgid = obj.portal_type url_href_title = u'%s at %s: %s' % \ (self.context.translate(type_title_msgid, context = self.request), path, safe_unicode(description)) modified = self.ulocalized_time(obj.modified()), # element css classes type_class = 'contenttype-' + \ plone_utils.normalizeString(obj.portal_type) state_class = '' states = {} for w in workflow.getWorkflowsFor(obj): state = w._getWorkflowStateOf(obj).id states[w.state_var] = state state_class += "state-%s " % state results_dict = dict( obj = obj, id = obj.getId, title = title, uid = uid, path = path, url = url, fti = fti, item_data = json.dumps([]), url_href_title = url_href_title, obj_type = obj.Type, size = obj.getObjSize, modified = modified, icon = icon.html_tag(), type_class = type_class, # a list of lookups for single-value-select fields choices = {}, state_class = state_class, relative_url = relative_url, view_url = url, table_row_class = "", # a list of names of fields that may be edited on this item allow_edit = [], # a list of names of fields that are compulsory (if editable) required = [], # "before", "after" and replace: dictionary (key is column ID) # A snippet of HTML which will be rendered # before/after/instead of the table cell content. before = {}, # { before : "<a href=..>" } after = {}, replace = {}, ) try: review_state = workflow.getInfoFor(obj, 'review_state') state_title = self.context.translate( PMF(workflow.getTitleForStateOnType(review_state, obj.portal_type))) except: review_state = 'active' state_title = None if review_state: results_dict['review_state'] = review_state for state_var, state in states.items(): if not state_title: state_title = workflow.getTitleForStateOnType( state, obj.portal_type) results_dict[state_var] = state results_dict['state_title'] = state_title # XXX add some kind of out-of-date indicator to bika listing ## if App.config.getConfiguration().debug_mode: ## from Products.CMFEditions.utilities import dereference ## pr = getToolByName(self.context, 'portal_repository') ## o = hasattr(obj, 'getObject') and obj.getObject() or obj ## if pr.isVersionable(o): ## pa = getToolByName(self.context, 'portal_archivist') ## history_id = str(dereference(o)[1]) ## version_id = hasattr(o, 'version_id') \ ## and str(o.version_id) or None ## if not 'version_id' in self.columns.keys(): ## self.columns['version_id'] = {'title':'version'} ## for x in range(len(self.review_states)): ## self.review_states[x]['columns'].append('version_id') ## results_dict['version_id'] = '%s/%s' % (version_id, history_id) # extra classes for individual fields on this item { field_id : "css classes" } results_dict['class'] = {} # Search for values for all columns in obj for key in self.columns.keys(): if hasattr(obj, key): # if the key is already in the results dict # then we don't replace it's value if results_dict.has_key(key): continue value = getattr(obj, key) if callable(value): value = value() results_dict[key] = value results.append(results_dict) return results
def __call__(self, result=None, specification=None, **kwargs): searchTerm = _c(self.request.get('searchTerm', '')).lower() force_all = self.request.get('force_all', 'false') searchFields = 'search_fields' in self.request \ and json.loads(_u(self.request.get('search_fields', '[]'))) \ or ('Title',) # lookup objects from ZODB catalog_name = _c(self.request.get('catalog_name', 'portal_catalog')) catalog = getToolByName(self.context, catalog_name) # N.B. We don't use json.loads to avoid unicode conversion, which will # fail in the catalog search for some cases # see: https://github.com/senaite/bika.lims/issues/443 base_query = ast.literal_eval(self.request['base_query']) search_query = ast.literal_eval(self.request.get('search_query', "{}")) # first with all queries contentFilter = dict((k, v) for k, v in base_query.items()) contentFilter.update(search_query) # Sorted by? (by default, Title) sort_on = self.request.get('sidx', 'Title') if sort_on == 'Title': sort_on = 'sortable_title' if sort_on: # Check if is an index and if is sortable. Otherwise, assume the # sorting must be done manually index = catalog.Indexes.get(sort_on, None) if index and index.meta_type in ['FieldIndex', 'DateIndex']: contentFilter['sort_on'] = sort_on # Sort order? sort_order = self.request.get('sord', 'asc') if (sort_order in ['desc', 'reverse', 'rev', 'descending']): contentFilter['sort_order'] = 'descending' else: contentFilter['sort_order'] = 'ascending' # Can do a search for indexes? criterias = [] fields_wo_index = [] if searchTerm: for field_name in searchFields: index = catalog.Indexes.get(field_name, None) if not index: fields_wo_index.append(field_name) continue if index.meta_type in ('ZCTextIndex'): if searchTerm.isspace(): # earchTerm != ' ' added because of # https://github.com/plone/Products.CMFPlone/issues # /1537 searchTerm = '' continue else: temp_st = searchTerm + '*' criterias.append(MatchRegexp(field_name, temp_st)) elif index.meta_type in ('FieldIndex'): criterias.append(MatchRegexp(field_name, searchTerm)) elif index.meta_type == 'DateIndex': msg = "Unhandled DateIndex search on '%s'" % field_name from bika.lims import logger logger.warn(msg) else: criterias.append(Generic(field_name, searchTerm)) if criterias: # Advanced search advanced_query = catalog.makeAdvancedQuery(contentFilter) aq_or = Or() for criteria in criterias: aq_or.addSubquery(criteria) advanced_query &= aq_or brains = catalog.evalAdvancedQuery(advanced_query) else: brains = catalog(contentFilter) if brains and searchTerm and fields_wo_index: _brains = [] for brain in brains: for field_name in fields_wo_index: value = getattr(brain, field_name, None) if not value: instance = brain.getObject() schema = instance.Schema() if field_name in schema: value = schema[field_name].get(instance) if callable(value): value = value() if value and value.lower().find(searchTerm) > -1: _brains.append(brain) break brains = _brains # Then just base_query alone ("show all if no match") if not brains and force_all.lower() == 'true': if search_query: brains = catalog(base_query) if brains and searchTerm: _brains = [p for p in brains if p.Title.lower().find(searchTerm) > -1] if _brains: brains = _brains return brains
def folderitems(self, full_objects=False): """ """ #self.contentsMethod = self.context.getFolderContents if not hasattr(self, 'contentsMethod'): self.contentsMethod = getToolByName(self.context, self.catalog) context = aq_inner(self.context) plone_layout = getMultiAdapter((context, self.request), name=u'plone_layout') plone_utils = getToolByName(context, 'plone_utils') plone_view = getMultiAdapter((context, self.request), name=u'plone') portal_properties = getToolByName(context, 'portal_properties') portal_types = getToolByName(context, 'portal_types') workflow = getToolByName(context, 'portal_workflow') site_properties = portal_properties.site_properties norm = getUtility(IIDNormalizer).normalize show_all = self.request.get('show_all', '').lower() == 'true' pagenumber = int(self.request.get('pagenumber', 1) or 1) pagesize = self.pagesize start = (pagenumber - 1) * pagesize end = start + pagesize if (hasattr(self, 'And') and self.And) \ or (hasattr(self, 'Or') and self.Or): # if contentsMethod is capable, we do an AdvancedQuery. if hasattr(self.contentsMethod, 'makeAdvancedQuery'): aq = self.contentsMethod.makeAdvancedQuery(self.contentFilter) if hasattr(self, 'And') and self.And: tmpAnd = And() for q in self.And: tmpAnd.addSubquery(q) aq &= tmpAnd if hasattr(self, 'Or') and self.Or: tmpOr = Or() for q in self.Or: tmpOr.addSubquery(q) aq &= tmpOr brains = self.contentsMethod.evalAdvancedQuery(aq) else: # otherwise, self.contentsMethod must handle contentFilter brains = self.contentsMethod(self.contentFilter) else: brains = self.contentsMethod(self.contentFilter) results = [] self.page_start_index = "" for i, obj in enumerate(brains): # we don't know yet if it's a brain or an object path = hasattr(obj, 'getPath') and obj.getPath() or \ "/".join(obj.getPhysicalPath()) # avoid creating unnecessary info for items outside the current # batch; only the path is needed for the "select all" case... if not show_all and not start <= i < end: if hasattr(obj, 'getObject'): uid = obj.UID else: uid = obj.UID() results.append(dict(path=path, uid=uid)) continue if self.page_start_index == "": self.page_start_index = i if hasattr(obj, 'getObject'): obj = obj.getObject() uid = obj.UID() title = obj.Title() description = obj.Description() icon = plone_layout.getIcon(obj) url = obj.absolute_url() relative_url = obj.absolute_url(relative=True) fti = portal_types.get(obj.portal_type) if fti is not None: type_title_msgid = fti.Title() else: type_title_msgid = obj.portal_type url_href_title = u'%s at %s: %s' % \ (self.context.translate(type_title_msgid, context = self.request), path, safe_unicode(description)) modified = self.ulocalized_time(obj.modified()), # element css classes type_class = 'contenttype-' + \ plone_utils.normalizeString(obj.portal_type) state_class = '' states = {} for w in workflow.getWorkflowsFor(obj): state = w._getWorkflowStateOf(obj).id states[w.state_var] = state state_class += "state-%s " % state results_dict = dict( obj=obj, id=obj.getId, title=title, uid=uid, path=path, url=url, fti=fti, item_data=json.dumps([]), url_href_title=url_href_title, obj_type=obj.Type, size=obj.getObjSize, modified=modified, icon=icon.html_tag(), type_class=type_class, # a list of lookups for single-value-select fields choices={}, state_class=state_class, relative_url=relative_url, view_url=url, table_row_class="", category='None', # a list of names of fields that may be edited on this item allow_edit=[], # a list of names of fields that are compulsory (if editable) required=[], # "before", "after" and replace: dictionary (key is column ID) # A snippet of HTML which will be rendered # before/after/instead of the table cell content. before={}, # { before : "<a href=..>" } after={}, replace={}, ) try: review_state = workflow.getInfoFor(obj, 'review_state') state_title = self.context.translate( PMF( workflow.getTitleForStateOnType( review_state, obj.portal_type))) except: review_state = 'active' state_title = None if review_state: results_dict['review_state'] = review_state for state_var, state in states.items(): if not state_title: state_title = workflow.getTitleForStateOnType( state, obj.portal_type) results_dict[state_var] = state results_dict['state_title'] = state_title # XXX add some kind of out-of-date indicator to bika listing ## if App.config.getConfiguration().debug_mode: ## from Products.CMFEditions.utilities import dereference ## pr = getToolByName(self.context, 'portal_repository') ## o = hasattr(obj, 'getObject') and obj.getObject() or obj ## if pr.isVersionable(o): ## pa = getToolByName(self.context, 'portal_archivist') ## history_id = str(dereference(o)[1]) ## version_id = hasattr(o, 'version_id') \ ## and str(o.version_id) or None ## if not 'version_id' in self.columns.keys(): ## self.columns['version_id'] = {'title':'version'} ## for x in range(len(self.review_states)): ## self.review_states[x]['columns'].append('version_id') ## results_dict['version_id'] = '%s/%s' % (version_id, history_id) # extra classes for individual fields on this item { field_id : "css classes" } results_dict['class'] = {} # Search for values for all columns in obj for key in self.columns.keys(): if hasattr(obj, key): # if the key is already in the results dict # then we don't replace it's value if results_dict.has_key(key): continue value = getattr(obj, key) if callable(value): value = value() results_dict[key] = value results.append(results_dict) return results
def folderitems(self, full_objects=False): """ >>> portal = layer['portal'] >>> portal_url = portal.absolute_url() >>> from plone.app.testing import SITE_OWNER_NAME >>> from plone.app.testing import SITE_OWNER_PASSWORD Test page batching https://github.com/bikalabs/Bika-LIMS/issues/1276 When visiting the second page, the Water sampletype should be displayed: >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD) >>> browser.open(portal_url+"/bika_setup/bika_sampletypes/folder_view?", ... "list_pagesize=10&list_review_state=default") >>> browser.contents '...Water...' """ #self.contentsMethod = self.context.getFolderContents if not hasattr(self, 'contentsMethod'): self.contentsMethod = getToolByName(self.context, self.catalog) context = aq_inner(self.context) plone_layout = getMultiAdapter((context, self.request), name=u'plone_layout') plone_utils = getToolByName(context, 'plone_utils') plone_view = getMultiAdapter((context, self.request), name=u'plone') portal_properties = getToolByName(context, 'portal_properties') portal_types = getToolByName(context, 'portal_types') workflow = getToolByName(context, 'portal_workflow') site_properties = portal_properties.site_properties norm = getUtility(IIDNormalizer).normalize if self.request.get('show_all', '').lower() == 'true' \ or self.show_all == True \ or self.pagesize == 0: show_all = True else: show_all = False if (hasattr(self, 'And') and self.And) \ or (hasattr(self, 'Or') and self.Or): # if contentsMethod is capable, we do an AdvancedQuery. if hasattr(self.contentsMethod, 'makeAdvancedQuery'): aq = self.contentsMethod.makeAdvancedQuery(self.contentFilter) if hasattr(self, 'And') and self.And: tmpAnd = And() for q in self.And: tmpAnd.addSubquery(q) aq &= tmpAnd if hasattr(self, 'Or') and self.Or: tmpOr = Or() for q in self.Or: tmpOr.addSubquery(q) aq &= tmpOr brains = self.contentsMethod.evalAdvancedQuery(aq) else: # otherwise, self.contentsMethod must handle contentFilter brains = self.contentsMethod(self.contentFilter) else: brains = self.contentsMethod(self.contentFilter) # idx increases one unit each time an object is added to the 'items' # dictionary to be returned. Note that if the item is not rendered, # the idx will not increase. idx = 0 results = [] self.show_more = False brains = brains[self.limit_from:] for i, obj in enumerate(brains): # avoid creating unnecessary info for items outside the current # batch; only the path is needed for the "select all" case... # we only take allowed items into account if not show_all and idx >= self.pagesize: # Maximum number of items to be shown reached! self.show_more = True break # we don't know yet if it's a brain or an object path = hasattr(obj, 'getPath') and obj.getPath() or \ "/".join(obj.getPhysicalPath()) # This item must be rendered, we need the object instead of a brain obj = obj.getObject() if hasattr(obj, 'getObject') else obj # check if the item must be rendered or not (prevents from # doing it later in folderitems) and dealing with paging if not obj or not self.isItemAllowed(obj): continue uid = obj.UID() title = obj.Title() description = obj.Description() icon = plone_layout.getIcon(obj) url = obj.absolute_url() relative_url = obj.absolute_url(relative=True) fti = portal_types.get(obj.portal_type) if fti is not None: type_title_msgid = fti.Title() else: type_title_msgid = obj.portal_type url_href_title = '%s at %s: %s' % (t(type_title_msgid), path, to_utf8(description)) modified = self.ulocalized_time(obj.modified()), # element css classes type_class = 'contenttype-' + \ plone_utils.normalizeString(obj.portal_type) state_class = '' states = {} for w in workflow.getWorkflowsFor(obj): state = w._getWorkflowStateOf(obj).id states[w.state_var] = state state_class += "state-%s " % state results_dict = dict( obj=obj, id=obj.getId(), title=title, uid=uid, path=path, url=url, fti=fti, item_data=json.dumps([]), url_href_title=url_href_title, obj_type=obj.Type, size=obj.getObjSize, modified=modified, icon=icon.html_tag(), type_class=type_class, # a list of lookups for single-value-select fields choices={}, state_class=state_class, relative_url=relative_url, view_url=url, table_row_class="", category='None', # a list of names of fields that may be edited on this item allow_edit=[], # a list of names of fields that are compulsory (if editable) required=[], # a dict where the column name works as a key and the value is # the name of the field related with the column. It is used # when the name given to the column and the content field it # represents diverges. bika_listing_table_items.pt defines an # attribute for each item, this attribute is named 'field' and # the system fills it taking advantage of this dictionary or # the name of the column if it isn't defined in the dict. field={}, # "before", "after" and replace: dictionary (key is column ID) # A snippet of HTML which will be rendered # before/after/instead of the table cell content. before={}, # { before : "<a href=..>" } after={}, replace={}, ) try: rs = workflow.getInfoFor(obj, 'review_state') st_title = workflow.getTitleForStateOnType(rs, obj.portal_type) st_title = t(PMF(st_title)) except: rs = 'active' st_title = None if rs: results_dict['review_state'] = rs for state_var, state in states.items(): if not st_title: st_title = workflow.getTitleForStateOnType( state, obj.portal_type) results_dict[state_var] = state results_dict['state_title'] = st_title # extra classes for individual fields on this item { field_id : "css classes" } results_dict['class'] = {} for name, adapter in getAdapters((obj, ), IFieldIcons): auid = obj.UID() if hasattr(obj, 'UID') and callable( obj.UID) else None if not auid: continue alerts = adapter() # logger.info(str(alerts)) if alerts and auid in alerts: if auid in self.field_icons: self.field_icons[auid].extend(alerts[auid]) else: self.field_icons[auid] = alerts[auid] # Search for values for all columns in obj for key in self.columns.keys(): # if the key is already in the results dict # then we don't replace it's value value = results_dict.get(key, '') if key not in results_dict: attrobj = getFromString(obj, key) value = attrobj if attrobj else value # Custom attribute? Inspect to set the value # for the current column dinamically vattr = self.columns[key].get('attr', None) if vattr: attrobj = getFromString(obj, vattr) value = attrobj if attrobj else value results_dict[key] = value # Replace with an url? replace_url = self.columns[key].get('replace_url', None) if replace_url: attrobj = getFromString(obj, replace_url) if attrobj: results_dict['replace'][key] = \ '<a href="%s">%s</a>' % (attrobj, value) # The item basics filled. Delegate additional actions to folderitem # service. folderitem service is frequently overriden by child objects item = self.folderitem(obj, results_dict, idx) if item: results.append(item) idx += 1 # Need manual_sort? # Note that the order has already been set in contentFilter, so # there is no need to reverse if self.manual_sort_on: results.sort(lambda x, y: cmp(x.get(self.manual_sort_on, ''), y.get(self.manual_sort_on, ''))) return results