Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 60 additions & 49 deletions glpi/glpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,15 @@ def search_options(self, item_name):

return response.json()

def search_engine(self, search_query):
def search_engine(self, search_query, params):
"""
Search an item by URI.
Use GLPI search engine passing parameter by URI.
#TODO could pass search criteria in payload, like others items
operations.
"""
new_uri = "%s/%s" % (self.uri, search_query)
response = self.request('GET', new_uri, accept_json=True)
response = self.request('GET', new_uri, params=params, accept_json=True)

return response.json()

Expand Down Expand Up @@ -672,7 +672,7 @@ def search(self, item_name, criteria):
else:
return {"message_error": "Unable to find a valid criteria."}

def search_engine(self, item_name, criteria):
def search_engine(self, item_name, params):
"""
Call GLPI's search engine syntax.

Expand All @@ -690,6 +690,17 @@ def search_engine(self, item_name, criteria):
GLPIs APIRest JSON formated with result of search in key 'data'.
"""

def field_to_int(field, field_map):
# if int given, use it directly
if isinstance(field, int) or field.isdigit():
return int(field)
# if name given, try to map to an int
elif field in field_map:
return field_map[field]
else:
raise GlpiInvalidArgument(
'Cannot map field name "' + field + '" to a field id.')

# Receive the possible field ids for type item_name
# -> to avoid wrong lookups, use uid of fields, but strip item type:
# example: {"1": {"uid": "Computer.name"}} gets {"name": 1}
Expand All @@ -702,64 +713,64 @@ def search_engine(self, item_name, criteria):
flags=re.IGNORECASE)
field_map[field_name] = int(field_id)

uri_query = "%s?" % item_name

for idx, c in enumerate(criteria['criteria']):
# build field argument
if idx == 0:
uri = ""
else:
uri = "&"
if 'field' in c and c['field'] is not None:
field_name = ""
# if int given, use it directly
if isinstance(c['field'], int) or c['field'].isdigit():
field_name = int(c['field'])
# if name given, try to map to an int
elif c['field'] in field_map:
field_name = field_map[c['field']]
def build_params_from_criteria(criteria, prefix):
for idx, c in enumerate(criteria):
if 'criteria' in c:
for param in build_params_from_criteria(
c['criteria'],
'%s[%d][criteria]' % (prefix, idx),
):
yield param
elif 'field' in c and c['field'] is not None:
yield (
"%s[%d][field]" % (prefix, idx),
field_to_int(c['field'], field_map),
)
else:
raise GlpiInvalidArgument(
'Cannot map field name "' + c['field'] + '" to ' +
'a field id for '+str(idx+1)+'. criterion '+str(c))
uri = uri + "criteria[%d][field]=%d" % (idx, field_name)
else:
raise GlpiInvalidArgument(
'Missing "field" parameter for ' + str(idx+1) +
'the criteria: ' + str(c))
'Missing "field" parameter for ' + str(idx+1) +
'the criteria: ' + str(c))

# build value argument
yield (
"%s[%d][value]" % (prefix, idx),
c.get('value', ''),
)

# build searchtype argument
# -> optional! defaults to "contains" on the server if empty
yield (
"%s[%d][searchtype]" % (prefix, idx),
c.get('searchtype', ''),
)

if 'link' in c:
yield (
"%s[%d][link]" % (prefix, idx),
c['link'],
)
elif idx > 0:
# link is optional for 1st criterion according to docs...
# -> error if not present but more than one criterion
raise GlpiInvalidArgument(
'Missing link type for '+str(idx+1)+'. criterion '+str(c))

# build value argument
if 'value' not in c or c['value'] is None:
uri = uri + "&criteria[%d][value]=" % (idx)
else:
uri = uri + "&criteria[%d][value]=%s" % (idx, c['value'])
params.update(build_params_from_criteria(params['criteria'], 'criteria'))

# build searchtype argument
# -> optional! defaults to "contains" on the server if empty
if 'searchtype' in c and c['searchtype'] is not None:
uri = (uri + "&criteria[%d][searchtype]=%s".format(idx,
c['searchtype']))
else:
uri = uri + "&criteria[%d][searchtype]=" % (idx)
del params['criteria']

# link is optional for 1st criterion according to docs...
# -> error if not present but more than one criterion
if 'link' not in c and idx > 0:
raise GlpiInvalidArgument(
'Missing link type for '+str(idx+1)+'. criterion '+str(c))
elif 'link' in c:
uri = uri + "&criteria[%d][link]=%s" % (idx, c['link'])
if 'forcedisplay' in params:
for idx, field in enumerate(params['forcedisplay']):
params['forcedisplay[%d]' % idx] = field_to_int(field, field_map)

# add this criterion to the query
uri_query = uri_query + uri
del params['forcedisplay']

try:
if not self.api_has_session():
self.init_api()

self.update_uri('search')
# TODO: is this call correct? shouldn't this be search_engine()?
return self.api_rest.search_options(uri_query)
return self.api_rest.search_engine(item_name, params)

except GlpiException as e:
return {'{}'.format(e)}
Expand Down