blob: a6cb46f4f34c5c70d18a8f4242f2b3e5aa566c22 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""Utility functions and classes for dealing with saved queries.
7
8Saved queries can be part of the project issue config, where they are
9called "canned queries". Or, they can be personal saved queries that
10may appear in the search scope drop-down, on the user's dashboard, or
11in the user's subscription.
12"""
13from __future__ import print_function
14from __future__ import division
15from __future__ import absolute_import
16
17import logging
18import re
19
20from framework import template_helpers
21from tracker import tracker_bizobj
22from tracker import tracker_constants
23
24
25MAX_QUERIES = 100
26
27
28def ParseSavedQueries(cnxn, post_data, project_service, prefix=''):
29 """Parse form data for the Saved Queries part of an admin form."""
30 saved_queries = []
31 for i in range(1, MAX_QUERIES + 1):
32 if ('%ssavedquery_name_%s' % (prefix, i)) not in post_data:
33 continue # skip any entries that are blank or have no predicate.
34
35 name = post_data['%ssavedquery_name_%s' % (prefix, i)].strip()
36 if not name:
37 continue # skip any blank entries
38
39 if '%ssavedquery_id_%s' % (prefix, i) in post_data:
40 query_id = int(post_data['%ssavedquery_id_%s' % (prefix, i)])
41 else:
42 query_id = None # a new query_id will be generated by the DB.
43
44 project_names_str = post_data.get(
45 '%ssavedquery_projects_%s' % (prefix, i), '')
46 project_names = [pn.strip().lower()
47 for pn in re.split('[],;\s]+', project_names_str)
48 if pn.strip()]
49 project_ids = list(project_service.LookupProjectIDs(
50 cnxn, project_names).values())
51
52 base_id = int(post_data['%ssavedquery_base_%s' % (prefix, i)])
53 query = post_data['%ssavedquery_query_%s' % (prefix, i)].strip()
54
55 subscription_mode_field = '%ssavedquery_sub_mode_%s' % (prefix, i)
56 if subscription_mode_field in post_data:
57 subscription_mode = post_data[subscription_mode_field].strip()
58 else:
59 subscription_mode = None
60
61 saved_queries.append(tracker_bizobj.MakeSavedQuery(
62 query_id, name, base_id, query, subscription_mode=subscription_mode,
63 executes_in_project_ids=project_ids))
64
65 return saved_queries
66
67
68class SavedQueryView(template_helpers.PBProxy):
69 """Wrapper class that makes it easier to display SavedQuery via EZT."""
70
71 def __init__(self, sq, idx, cnxn, project_service):
72 """Store relevant values for later display by EZT.
73
74 Args:
75 sq: A SavedQuery protocol buffer.
76 idx: Int index of this saved query in the list.
77 cnxn: connection to SQL database.
78 project_service: persistence layer for project data.
79 """
80 super(SavedQueryView, self).__init__(sq)
81
82 self.idx = idx
83 base_query_name = 'All issues'
84 for canned in tracker_constants.DEFAULT_CANNED_QUERIES:
85 qid, name, _base_id, _query = canned
86 if qid == sq.base_query_id:
87 base_query_name = name
88
89 if cnxn:
90 project_names = sorted(project_service.LookupProjectNames(
91 cnxn, sq.executes_in_project_ids).values())
92 self.projects = ', '.join(project_names)
93 else:
94 self.projects = ''
95
96 self.docstring = '[%s] %s' % (base_query_name, sq.query)
97
98
99def SavedQueryToCond(saved_query):
100 """Convert a SavedQuery PB to a user query condition string."""
101 if saved_query is None:
102 return ''
103
104 base_cond = tracker_bizobj.GetBuiltInQuery(saved_query.base_query_id)
105 cond = '%s %s' % (base_cond, saved_query.query)
106 return cond.strip()
107
108
109def SavedQueryIDToCond(cnxn, features_service, query_id):
110 """Convert a can/query ID to a user query condition string."""
111 built_in = tracker_bizobj.GetBuiltInQuery(query_id)
112 if built_in:
113 return built_in
114
115 saved_query = features_service.GetSavedQuery(cnxn, query_id)
116 return SavedQueryToCond(saved_query)