PageRenderTime 57ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/tr_query.cgi

https://code.google.com/p/bugzilla4intranet/
Perl | 419 lines | 343 code | 52 blank | 24 comment | 21 complexity | 1a85a4c2c448a08c516462ad12d99238 MD5 | raw file
  1. #!/usr/bin/perl -wT
  2. # -*- Mode: perl; indent-tabs-mode: nil -*-
  3. #
  4. # The contents of this file are subject to the Mozilla Public
  5. # License Version 1.1 (the "License"); you may not use this file
  6. # except in compliance with the License. You may obtain a copy of
  7. # the License at http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS
  10. # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11. # implied. See the License for the specific language governing
  12. # rights and limitations under the License.
  13. #
  14. # The Original Code is the Bugzilla Test Runner System.
  15. #
  16. # The Initial Developer of the Original Code is Maciej Maczynski.
  17. # Portions created by Maciej Maczynski are Copyright (C) 2001
  18. # Maciej Maczynski. All Rights Reserved.
  19. #
  20. # Contributor(s): Maciej Maczynski <macmac@xdsnet.pl>
  21. # Ed Fuentetaja <efuentetaja@acm.org>
  22. # Greg Hendricks <ghendricks@novell.com>
  23. use strict;
  24. use lib qw(. lib);
  25. use Bugzilla::Constants;
  26. use lib (bz_locations()->{extensionsdir} . '/testopia/lib');
  27. use Bugzilla;
  28. use Bugzilla::Util;
  29. use Bugzilla::Error;
  30. use Bugzilla::Field;
  31. use Testopia::Constants;
  32. use Testopia::Util;
  33. use Testopia::Classification;
  34. use Testopia::TestPlan;
  35. use Testopia::TestRun;
  36. use Testopia::TestCase;
  37. use Testopia::Environment::Category;
  38. use Testopia::Environment::Element;
  39. use Testopia::Environment::Property;
  40. use JSON;
  41. local our $vars = {};
  42. my $dbh = Bugzilla->dbh;
  43. local our $cgi = Bugzilla->cgi;
  44. local our $template = Bugzilla->template;
  45. Bugzilla->login(LOGIN_REQUIRED);
  46. Bugzilla->error_mode(ERROR_MODE_AJAX);
  47. sub convert_bugzilla_fields {
  48. my $field = shift;
  49. my $values = get_legal_field_values($field);
  50. my @vals;
  51. foreach my $v (@$values){
  52. push @vals, {name => $v, id => $v};
  53. }
  54. return \@vals;
  55. }
  56. sub get_searchable_objects{
  57. my $object = shift;
  58. my $dbh = Bugzilla->dbh;
  59. my $products = Bugzilla->user->get_selectable_products;
  60. my @ids;
  61. foreach my $p (@{$products}){
  62. push @ids, $p->id;
  63. }
  64. my $ref;
  65. SWITCH: for ($object) {
  66. /^components/ && do {
  67. $ref = $dbh->selectall_arrayref(
  68. "SELECT DISTINCT name AS id, name
  69. FROM components WHERE product_id IN (". join(",",@ids) .")
  70. ORDER BY name", {'Slice'=>{}});
  71. last SWITCH;
  72. };
  73. /^categories/ && do {
  74. $ref = $dbh->selectall_arrayref(
  75. "SELECT DISTINCT name AS id, name
  76. FROM test_case_categories WHERE product_id IN (". join(",",@ids) .")
  77. ORDER BY name", {'Slice'=>{}});
  78. last SWITCH;
  79. };
  80. /^builds/ && do {
  81. $ref = $dbh->selectall_arrayref(
  82. "SELECT DISTINCT name AS id, name
  83. FROM test_builds WHERE product_id IN (". join(",",@ids) .")
  84. ORDER BY name", {'Slice'=>{}});
  85. last SWITCH;
  86. };
  87. /^versions/ && do {
  88. $ref = $dbh->selectall_arrayref(
  89. "SELECT DISTINCT value AS id, value AS name
  90. FROM versions WHERE product_id IN (". join(",",@ids) .")
  91. ORDER BY name", {'Slice'=>{}});
  92. last SWITCH;
  93. };
  94. /^milestones/ && do {
  95. $ref = $dbh->selectall_arrayref(
  96. "SELECT DISTINCT value AS id, value AS name
  97. FROM milestones WHERE product_id IN (". join(",",@ids) .")
  98. ORDER BY name", {'Slice'=>{}});
  99. last SWITCH;
  100. };
  101. /^environments/ && do {
  102. $ref = $dbh->selectall_arrayref(
  103. "SELECT DISTINCT name AS id, name
  104. FROM test_environments WHERE product_id IN (". join(",",@ids) .")
  105. ORDER BY name", {'Slice'=>{}});
  106. last SWITCH;
  107. };
  108. }
  109. return $ref;
  110. }
  111. my $action = $cgi->param('action') || '';
  112. if ($action eq 'getversions'){
  113. $cgi->send_header;
  114. my @prod_ids;
  115. my $type = $cgi->param('type');
  116. my @values = split(",",$cgi->param('value'));
  117. my $obj;
  118. my @products;
  119. my $prodinfo;
  120. my $selectTypes = [qw{version milestone component build category environment}];
  121. foreach my $value (@values){
  122. if ($type eq 'classification'){
  123. $obj = Testopia::Classification->new({name => $value});
  124. next unless ($obj && scalar(grep {$_->name eq $obj->name} @{Bugzilla->user->get_selectable_classifications}));
  125. push @products, @{$obj->user_visible_products()};
  126. my @prod_names;
  127. push @prod_names, $_->name foreach @products;
  128. $prodinfo->{'product'} = \@prod_names;
  129. unshift @$selectTypes, "product";
  130. }
  131. else {
  132. trim($value);
  133. $obj = Bugzilla::Product->new({name => $value});
  134. next unless ($obj && Bugzilla->user->can_see_product($obj->name));
  135. push @products, $obj;
  136. }
  137. }
  138. unless (scalar @products > 0){
  139. push @products, @{Bugzilla->user->get_selectable_products};
  140. unshift @$selectTypes, "product";
  141. my @prod_names;
  142. push @prod_names, $_->name foreach @products;
  143. $prodinfo->{'product'} = \@prod_names;
  144. }
  145. push @prod_ids, $_->id foreach (@products);
  146. my $prod_ids = join(",", @prod_ids);
  147. my $dbh = Bugzilla->dbh;
  148. $prodinfo->{'version'} = $dbh->selectcol_arrayref("SELECT DISTINCT value FROM versions WHERE product_id IN ($prod_ids)");
  149. $prodinfo->{'milestone'} = $dbh->selectcol_arrayref("SELECT DISTINCT value FROM milestones WHERE product_id IN ($prod_ids)");
  150. $prodinfo->{'component'} = $dbh->selectcol_arrayref("SELECT DISTINCT name FROM components WHERE product_id IN ($prod_ids)");
  151. $prodinfo->{'build'} = $dbh->selectcol_arrayref("SELECT DISTINCT name FROM test_builds WHERE product_id IN ($prod_ids)");
  152. $prodinfo->{'category'} = $dbh->selectcol_arrayref("SELECT DISTINCT name FROM test_case_categories WHERE product_id IN ($prod_ids)");
  153. $prodinfo->{'environment'} = $dbh->selectcol_arrayref("SELECT DISTINCT name FROM test_environments WHERE product_id IN ($prod_ids)");
  154. # This list must match the name of the select fields and the names above
  155. $prodinfo->{'selectTypes'} = $selectTypes;
  156. my $json = new JSON;
  157. print "{'success': true, objects: " . $json->encode($prodinfo) . "}";
  158. }
  159. elsif ($action eq 'get_products'){
  160. $cgi->send_header;
  161. my @prod;
  162. if (Bugzilla->params->{'useclassification'}){
  163. my @classes = $cgi->param('class_ids');
  164. foreach my $id (@classes){
  165. my $class = Testopia::Classification->new($id);
  166. push @prod, @{$class->user_visible_products};
  167. }
  168. }
  169. else {
  170. @prod = Bugzilla->user->get_selectable_products;
  171. }
  172. my $ret;
  173. foreach my $e (@prod){
  174. $ret .= $e->{'id'}.'||'.$e->{'name'}.'|||';
  175. }
  176. chop($ret);
  177. print $ret;
  178. }
  179. elsif ($action eq 'get_categories'){
  180. $cgi->send_header;
  181. my @prod_ids = $cgi->param('prod_id');
  182. my $ret;
  183. foreach my $prod_id (@prod_ids){
  184. detaint_natural($prod_id);
  185. my $cat = Testopia::Environment::Category->new({});
  186. my $cats_ref = $cat->get_element_categories_by_product($prod_id);
  187. foreach my $e (@{$cats_ref}){
  188. $ret .= $e->id.'||'.$e->name.'|||';
  189. }
  190. }
  191. chop($ret);
  192. print $ret;
  193. }
  194. elsif ($action eq 'get_elements'){
  195. $cgi->send_header;
  196. my @cat_ids = $cgi->param('cat_id');
  197. my $ret;
  198. my @elmnts;
  199. foreach my $cat_id (@cat_ids){
  200. detaint_natural($cat_id);
  201. my $cat = Testopia::Environment::Category->new($cat_id);
  202. my $elmnts_ref = $cat->get_elements_by_category($cat->{'name'});
  203. foreach my $e (@{$elmnts_ref}){
  204. push @elmnts, Testopia::Environment::Element->new($e->{'element_id'});
  205. }
  206. }
  207. foreach my $e (@elmnts){
  208. $ret .= $e->id.'||'.$e->name.'|||';
  209. }
  210. chop($ret);
  211. print $ret;
  212. }
  213. elsif ($action eq 'get_properties'){
  214. $cgi->send_header;
  215. my @elmnt_ids = $cgi->param('elmnt_id');
  216. my $ret;
  217. foreach my $elmnt_id (@elmnt_ids){
  218. detaint_natural($elmnt_id);
  219. my $elmnt = Testopia::Environment::Element->new($elmnt_id);
  220. my $props = $elmnt->get_properties();
  221. foreach my $e (@{$props}){
  222. $ret .= $e->id.'||'.$e->name.'|||';
  223. }
  224. }
  225. chop($ret);
  226. print $ret;
  227. }
  228. elsif ($action eq 'get_valid_exp'){
  229. $cgi->send_header;
  230. my @prop_ids = $cgi->param('prop_id');
  231. my $ret;
  232. foreach my $prop_id (@prop_ids){
  233. detaint_natural($prop_id);
  234. my $prop = Testopia::Environment::Property->new($prop_id);
  235. my $exp = $prop->validexp;
  236. my @exps = split /\|/, $exp;
  237. foreach my $exp (@exps){
  238. $ret .=$exp.'|||';
  239. }
  240. }
  241. chop($ret);
  242. print $ret;
  243. }
  244. elsif ($action eq 'save_query'){
  245. $cgi->send_header;
  246. my $query = $cgi->param('query_part');
  247. my $qname = $cgi->param('query_name');
  248. my $type = $cgi->param('type');
  249. ThrowUserError('query_name_missing') unless $qname;
  250. trick_taint($query);
  251. trick_taint($qname);
  252. detaint_natural($type);
  253. $type ||= SAVED_SEARCH;
  254. my ($name) = $dbh->selectrow_array(
  255. "SELECT name
  256. FROM test_named_queries
  257. WHERE userid = ?
  258. AND name = ?",
  259. undef,(Bugzilla->user->id, $qname));
  260. if ($name){
  261. $dbh->do(
  262. "UPDATE test_named_queries
  263. SET query = ?
  264. WHERE userid = ?
  265. AND name = ?",
  266. undef,($query, Bugzilla->user->id, $qname));
  267. $vars->{'tr_message'} = "Updated saved search '$qname'";
  268. }
  269. else{
  270. my $quoted_qname = url_quote($qname);
  271. $query .= "&qname=$quoted_qname" unless $type == 3;
  272. $dbh->do("INSERT INTO test_named_queries
  273. VALUES(?,?,?,?,?)",
  274. undef, (Bugzilla->user->id, $qname, 1, $query, $type));
  275. $vars->{'tr_message'} = "Search saved as '$qname'";
  276. }
  277. print "{'success': true}";
  278. }
  279. elsif ($action eq 'delete_query'){
  280. $cgi->send_header;
  281. my $qname = $cgi->param('query_name');
  282. trick_taint($qname);
  283. $dbh->do("DELETE FROM test_named_queries WHERE userid = ? AND name = ?",
  284. undef, (Bugzilla->user->id, $qname));
  285. $vars->{'tr_message'} = "Testopia Saved Search '$qname' Deleted";
  286. print "{'success': true}";
  287. }
  288. elsif ($action eq 'get_saved_searches'){
  289. $cgi->send_header;
  290. my $type = $cgi->param('type');
  291. my $user = $cgi->param('userid') || Bugzilla->user->id;
  292. detaint_natural($type);
  293. detaint_natural($user);
  294. $type ||= SAVED_SEARCH;
  295. my $ref = $dbh->selectall_arrayref(
  296. "SELECT tnq.name, query, profiles.realname AS author, type
  297. FROM test_named_queries AS tnq
  298. INNER JOIN profiles ON tnq.userid = profiles.userid
  299. WHERE tnq.userid = ? AND isvisible = 1
  300. AND type = ?",
  301. {'Slice' =>{}} ,($user, $type));
  302. print "{'searches':" . to_json($ref) . "}";
  303. }
  304. else{
  305. #TODO: Support default query
  306. my $tab = $cgi->param('current_tab') || '';
  307. if ($tab eq 'plan'){
  308. $vars->{'plan'} = Testopia::TestPlan->new({});
  309. $vars->{'title'} = "Search For Test Plans";
  310. $vars->{'versions'} = get_searchable_objects('versions');
  311. }
  312. elsif ($tab eq 'run'){
  313. $vars->{'title'} = "Search For Test Runs";
  314. $vars->{'run'} = Testopia::TestRun->new({});;
  315. $vars->{'versions'} = get_searchable_objects('versions');
  316. $vars->{'milestones'} = get_searchable_objects('milestones');
  317. $vars->{'builds'} = get_searchable_objects('builds');
  318. $vars->{'environments'} = get_searchable_objects('environments');
  319. }
  320. elsif ($tab eq 'environment'){
  321. $vars->{'title'} = "Search For Test Run Environments";
  322. $vars->{'classifications'} = Bugzilla->user->get_selectable_classifications;
  323. $vars->{'products'} = Bugzilla->user->get_selectable_products;
  324. $vars->{'env'} = Testopia::Environment->new({});
  325. }
  326. elsif ($tab eq 'case_run'){
  327. $vars->{'title'} = "Search For Test Case-Runs";
  328. $vars->{'case'} = Testopia::TestCase->new({});
  329. $vars->{'run'} = Testopia::TestRun->new({});
  330. $vars->{'caserun'} = Testopia::TestCaseRun->new({});
  331. $vars->{'versions'} = get_searchable_objects('versions');
  332. $vars->{'milestones'} = get_searchable_objects('milestones');
  333. $vars->{'builds'} = get_searchable_objects('builds');
  334. $vars->{'environments'} = get_searchable_objects('environments');
  335. $vars->{'components'} = get_searchable_objects('components');
  336. $vars->{'categories'} = get_searchable_objects('categories');
  337. $vars->{'bug_status'} = convert_bugzilla_fields('bug_status');
  338. $vars->{'rep_platform'} = convert_bugzilla_fields('rep_platform');
  339. $vars->{'op_sys'} = convert_bugzilla_fields('op_sys');
  340. $vars->{'bug_priority'} = convert_bugzilla_fields('priority');
  341. $vars->{'bug_severity'} = convert_bugzilla_fields('bug_severity');
  342. $vars->{'resolution'} = convert_bugzilla_fields('resolution');
  343. }
  344. elsif ($tab eq 'case') {
  345. $tab = 'case';
  346. my $case = Testopia::TestCase->new({ 'case_id' => 0 });
  347. $vars->{'title'} = "Search For Test Cases";
  348. $vars->{'case'} = $case;
  349. $vars->{'components'} = get_searchable_objects('components');
  350. $vars->{'categories'} = get_searchable_objects('categories');
  351. $vars->{'bug_status'} = convert_bugzilla_fields('bug_status');
  352. $vars->{'rep_platform'} = convert_bugzilla_fields('rep_platform');
  353. $vars->{'op_sys'} = convert_bugzilla_fields('op_sys');
  354. $vars->{'bug_priority'} = convert_bugzilla_fields('priority');
  355. $vars->{'bug_severity'} = convert_bugzilla_fields('bug_severity');
  356. $vars->{'resolution'} = convert_bugzilla_fields('resolution');
  357. }
  358. else{
  359. print "Location: tr_show_product.cgi?search=1 \n\n";
  360. exit;
  361. }
  362. $cgi->send_header;
  363. $vars->{'report'} = $cgi->param('report');
  364. $vars->{'current_tab'} = $tab;
  365. $template->process("testopia/search/advanced.html.tmpl", $vars)
  366. || ThrowTemplateError($template->error());
  367. }