1<?php
2# MantisBT - A PHP based bugtracking system
3
4# MantisBT is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 2 of the License, or
7# (at your option) any later version.
8#
9# MantisBT is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with MantisBT.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * This page allows actions to be performed on an array of bugs
19 *
20 * @package MantisBT
21 * @copyright Copyright 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
22 * @copyright Copyright 2002  MantisBT Team - mantisbt-dev@lists.sourceforge.net
23 * @link http://www.mantisbt.org
24 *
25 * @uses core.php
26 * @uses access_api.php
27 * @uses authentication_api.php
28 * @uses bug_api.php
29 * @uses bug_group_action_api.php
30 * @uses config_api.php
31 * @uses constant_inc.php
32 * @uses custom_field_api.php
33 * @uses event_api.php
34 * @uses form_api.php
35 * @uses gpc_api.php
36 * @uses helper_api.php
37 * @uses lang_api.php
38 * @uses print_api.php
39 * @uses string_api.php
40 * @uses utility_api.php
41 * @uses version_api.php
42 */
43
44require_once( 'core.php' );
45require_api( 'access_api.php' );
46require_api( 'authentication_api.php' );
47require_api( 'bug_api.php' );
48require_api( 'bug_group_action_api.php' );
49require_api( 'config_api.php' );
50require_api( 'constant_inc.php' );
51require_api( 'custom_field_api.php' );
52require_api( 'event_api.php' );
53require_api( 'form_api.php' );
54require_api( 'gpc_api.php' );
55require_api( 'helper_api.php' );
56require_api( 'lang_api.php' );
57require_api( 'print_api.php' );
58require_api( 'string_api.php' );
59require_api( 'utility_api.php' );
60require_api( 'version_api.php' );
61
62auth_ensure_user_authenticated();
63
64$f_action = gpc_get_string( 'action', '' );
65$f_bug_arr = gpc_get_int_array( 'bug_arr', array() );
66
67# redirects to all_bug_page if nothing is selected
68if( is_blank( $f_action ) || ( 0 == count( $f_bug_arr ) ) ) {
69	print_header_redirect( 'view_all_bug_page.php' );
70}
71
72# run through the issues to see if they are all from one project
73$t_project_id = ALL_PROJECTS;
74$t_multiple_projects = false;
75$t_user = auth_get_current_user_id();
76$t_projects = array();
77$t_view_bug_threshold = array();
78
79bug_cache_array_rows( $f_bug_arr );
80
81foreach( $f_bug_arr as $t_key => $t_bug_id ) {
82	$t_bug = bug_get( $t_bug_id );
83
84	# Per-project cache of the access threshold
85	if( !isset( $t_view_bug_threshold[$t_bug->project_id] ) ) {
86		$t_view_bug_threshold[$t_bug->project_id] = config_get(
87			'view_bug_threshold',
88			null,
89			$t_user,
90			$t_bug->project_id
91		);
92	}
93
94	# Remove any issues the user doesn't have access to
95	if( !access_has_bug_level( $t_view_bug_threshold[$t_bug->project_id], $t_bug_id ) ) {
96		unset( $f_bug_arr[$t_key] );
97		continue;
98	}
99
100	# Multiple projects check
101	if( $t_project_id != $t_bug->project_id ) {
102		if( ( $t_project_id != ALL_PROJECTS ) && !$t_multiple_projects ) {
103			$t_multiple_projects = true;
104		} else {
105			$t_project_id = $t_bug->project_id;
106			$t_projects[$t_project_id] = $t_project_id;
107		}
108	}
109}
110
111# Array of parameters to be used with plugin event
112$t_event_params = array();
113$t_event_params['bug_ids'] = $f_bug_arr;
114$t_event_params['action'] = $f_action;
115$t_event_params['has_bugnote'] = false;
116$t_event_params['multiple_projects'] = $t_multiple_projects;
117
118if( $t_multiple_projects ) {
119	$t_project_id = ALL_PROJECTS;
120	$t_projects[ALL_PROJECTS] = ALL_PROJECTS;
121}
122# override the project if necessary
123if( $t_project_id != helper_get_current_project() ) {
124	# in case the current project is not the same project of the bug we are viewing...
125	# ... override the current project. This to avoid problems with categories and handlers lists etc.
126	$g_project_override = $t_project_id;
127}
128
129define( 'BUG_ACTIONGROUP_INC_ALLOW', true );
130
131$t_finished = false;
132$t_bugnote = false;
133
134$t_external_action_prefix = 'EXT_';
135if( strpos( $f_action, $t_external_action_prefix ) === 0 ) {
136	$t_form_page = 'bug_actiongroup_ext_page.php';
137	require_once( $t_form_page );
138	exit;
139}
140
141$t_custom_group_actions = config_get( 'custom_group_actions' );
142
143foreach( $t_custom_group_actions as $t_custom_group_action ) {
144	if( $f_action == $t_custom_group_action['action'] ) {
145		require_once( $t_custom_group_action['form_page'] );
146		exit;
147	}
148}
149
150# Check if user selected to update a custom field.
151$t_custom_fields_prefix = 'custom_field_';
152if( strpos( $f_action, $t_custom_fields_prefix ) === 0 ) {
153	$t_custom_field_id = (int)substr( $f_action, mb_strlen( $t_custom_fields_prefix ) );
154	$f_action = 'CUSTOM';
155	$t_event_params['action'] = $f_action;
156}
157
158# Form name
159$t_form_name = 'bug_actiongroup_' . $f_action;
160
161switch( $f_action ) {
162	# Use a simple confirmation page, if close or delete...
163	case 'CLOSE' :
164		$t_finished 			= true;
165		$t_question_title 		= lang_get( 'close_bugs_conf_msg' );
166		$t_button_title 		= lang_get( 'close_group_bugs_button' );
167		$t_bugnote				= true;
168		break;
169	case 'DELETE' :
170		$t_finished 			= true;
171		$t_question_title		= lang_get( 'delete_bugs_conf_msg' );
172		$t_button_title 		= lang_get( 'delete_group_bugs_button' );
173		break;
174	case 'SET_STICKY' :
175		$t_finished 			= true;
176		$t_question_title		= lang_get( 'set_sticky_bugs_conf_msg' );
177		$t_button_title 		= lang_get( 'set_sticky_group_bugs_button' );
178		break;
179	# ...else we define the variables used in the form
180	case 'MOVE' :
181		$t_question_title 		= lang_get( 'move_bugs_conf_msg' );
182		$t_button_title 		= lang_get( 'move_group_bugs_button' );
183		$t_form					= 'project_id';
184		break;
185	case 'COPY' :
186		$t_question_title 		= lang_get( 'copy_bugs_conf_msg' );
187		$t_button_title 		= lang_get( 'copy_group_bugs_button' );
188		$t_form					= 'project_id';
189		break;
190	case 'ASSIGN' :
191		$t_question_title 		= lang_get( 'assign_bugs_conf_msg' );
192		$t_button_title 		= lang_get( 'assign_group_bugs_button' );
193		$t_form 				= 'assign';
194		break;
195	case 'RESOLVE' :
196		$t_question_title 		= lang_get( 'resolve_bugs_conf_msg' );
197		$t_button_title 		= lang_get( 'resolve_group_bugs_button' );
198		$t_form 				= 'resolution';
199		if( ALL_PROJECTS != $t_project_id ) {
200			$t_question_title2 = lang_get( 'fixed_in_version' );
201			$t_form2 = 'fixed_in_version';
202		}
203		$t_bugnote				= true;
204		break;
205	case 'UP_PRIOR' :
206		$t_question_title 		= lang_get( 'priority_bugs_conf_msg' );
207		$t_button_title 		= lang_get( 'priority_group_bugs_button' );
208		$t_form 				= 'priority';
209		break;
210	case 'UP_STATUS' :
211		$t_question_title 		= lang_get( 'status_bugs_conf_msg' );
212		$t_button_title 		= lang_get( 'status_group_bugs_button' );
213		$t_form 				= 'status';
214		$t_bugnote				= true;
215		break;
216	case 'UP_CATEGORY' :
217		$t_question_title		= lang_get( 'category_bugs_conf_msg' );
218		$t_button_title			= lang_get( 'category_group_bugs_button' );
219		$t_form					= 'category';
220		break;
221	case 'VIEW_STATUS' :
222		$t_question_title		= lang_get( 'view_status_bugs_conf_msg' );
223		$t_button_title			= lang_get( 'view_status_group_bugs_button' );
224		$t_form					= 'view_status';
225		break;
226	case 'UP_PRODUCT_VERSION':
227		$t_question_title		= lang_get( 'product_version_bugs_conf_msg' );
228		$t_button_title			= lang_get( 'product_version_group_bugs_button' );
229		$t_form					= 'product_version';
230		break;
231	case 'UP_FIXED_IN_VERSION':
232		$t_question_title		= lang_get( 'fixed_in_version_bugs_conf_msg' );
233		$t_button_title			= lang_get( 'fixed_in_version_group_bugs_button' );
234		$t_form					= 'fixed_in_version';
235		break;
236	case 'UP_TARGET_VERSION':
237		$t_question_title		= lang_get( 'target_version_bugs_conf_msg' );
238		$t_button_title			= lang_get( 'target_version_group_bugs_button' );
239		$t_form					= 'target_version';
240		break;
241	case 'UP_DUE_DATE':
242		$t_question_title		= lang_get( 'due_date_bugs_conf_msg' );
243		$t_button_title			= lang_get( 'due_date_group_bugs_button' );
244		$t_form					= 'due_date';
245		break;
246	case 'CUSTOM' :
247		$t_custom_field_def = custom_field_get_definition( $t_custom_field_id );
248		$t_question_title = sprintf( lang_get( 'actiongroup_menu_update_field' ),
249			string_attribute( lang_get_defaulted( $t_custom_field_def['name'] ) )
250		);
251		$t_button_title = $t_question_title;
252		$t_form = 'custom_field_' . $t_custom_field_id;
253		$t_event_params['custom_field_id'] = $t_custom_field_id;
254		break;
255	default:
256		trigger_error( ERROR_GENERIC, ERROR );
257}
258$t_event_params['has_bugnote'] = $t_bugnote;
259
260bug_group_action_print_top();
261?>
262
263<div class="col-md-12 col-xs-12">
264<?php
265if( $t_multiple_projects ) {
266	echo '<div class="alert alert-warning"> <p class="bold">' . lang_get( 'multiple_projects' ) . '</p> </div>';
267}
268?>
269<div id="action-group-div" class="form-container">
270	<form method="post" action="bug_actiongroup.php">
271		<?php echo form_security_field( $t_form_name ); ?>
272		<input type="hidden" name="action" value="<?php echo string_attribute( $f_action ) ?>" />
273<?php
274	bug_group_action_print_hidden_fields( $f_bug_arr );
275	if( $f_action === 'CUSTOM' ) {
276		echo "<input type=\"hidden\" name=\"custom_field_id\" value=\"$t_custom_field_id\" />";
277	}
278?>
279<div class="widget-box widget-color-blue2">
280<div class="widget-header widget-header-small">
281	<h4 class="widget-title lighter">
282		<?php echo $t_question_title ?>
283	</h4>
284</div>
285<div class="widget-body">
286	<div class="widget-main no-padding">
287		<div class="table-responsive">
288			<table class="table table-bordered table-condensed table-striped">
289			<tbody>
290<?php
291	if( !$t_finished ) {
292?>
293				<tr>
294					<th class="category">
295						<?php echo $t_question_title ?>
296					</th>
297					<td>
298<?php
299		if( $f_action === 'CUSTOM' ) {
300			$t_custom_field_def = custom_field_get_definition( $t_custom_field_id );
301
302			$t_bug_id = null;
303
304			# if there is only one issue, use its current value as default, otherwise,
305			# use the default value specified in custom field definition.
306			if( count( $f_bug_arr ) == 1 ) {
307				$t_bug_id = $f_bug_arr[0];
308			}
309
310			print_custom_field_input( $t_custom_field_def, $t_bug_id );
311		} else if ( $f_action === 'UP_DUE_DATE' ) {
312			$t_date_to_display = '';
313			# if there is only one issue, use its current value as default
314			if( count( $f_bug_arr ) == 1 ) {
315				$t_bug_id = $f_bug_arr[0];
316				$t_bug = bug_get( $t_bug_id );
317				if( !date_is_null( $t_bug->due_date ) ) {
318					$t_date_to_display = date( config_get( 'normal_date_format' ), $t_bug->due_date );
319				}
320			}
321
322			echo '<input type="text" id="due_date" name="due_date" class="datetimepicker input-sm" size="16" maxlength="16" ' .
323				'data-picker-locale="' . lang_get_current_datetime_locale() .
324				'" data-picker-format="' . config_get( 'datetime_picker_format' ) . '"' .
325				'" value="' . $t_date_to_display . '" />';
326			print_icon( 'fa-calendar', 'fa-xlg datetimepicker' );
327		} else {
328			echo '<select name="' . $t_form . '" class="input-sm" required>';
329
330			switch( $f_action ) {
331				case 'COPY':
332				case 'MOVE':
333					print_project_option_list( null /* $p_project_id */, false /* $p_include_all_projects */,
334							null /* $p_filter_project_id */, false /* $p_trace */, true /* $p_can_report_only */ );
335					break;
336				case 'ASSIGN':
337					print_assign_to_option_list( 0, $t_project_id );
338					break;
339				case 'RESOLVE':
340					print_enum_string_option_list( 'resolution', config_get( 'bug_resolution_fixed_threshold' ) );
341					break;
342				case 'UP_PRIOR':
343					print_enum_string_option_list( 'priority', config_get( 'default_bug_priority' ) );
344					break;
345				case 'UP_STATUS':
346					print_enum_string_option_list( 'status', config_get( 'bug_submit_status' ) );
347					break;
348				case 'UP_CATEGORY':
349					print_category_option_list();
350					break;
351				case 'VIEW_STATUS':
352					print_enum_string_option_list( 'view_state', config_get( 'default_bug_view_status' ) );
353					break;
354				case 'UP_TARGET_VERSION':
355					print_version_option_list( '', $t_projects, VERSION_FUTURE, true );
356					break;
357				case 'UP_PRODUCT_VERSION':
358				case 'UP_FIXED_IN_VERSION':
359					print_version_option_list( '', $t_projects, VERSION_ALL, true );
360					break;
361			}
362
363			echo '</select>';
364		}
365?>
366					</td>
367				</tr>
368<?php
369		if( isset( $t_question_title2 ) ) {
370			switch( $f_action ) {
371				case 'RESOLVE':
372					$t_show_product_version = ( ON == config_get( 'show_product_version' ) )
373						|| ( ( AUTO == config_get( 'show_product_version' ) )
374									&& ( count( version_get_all_rows( $t_project_id ) ) > 0 ) );
375					if( $t_show_product_version ) {
376?>
377				<tr>
378					<th class="category">
379						<?php echo $t_question_title2 ?>
380					</th>
381					<td>
382						<select name="<?php echo $t_form2 ?>" class="input-sm">
383							<?php print_version_option_list( '', null, VERSION_ALL );?>
384						</select>
385					</td>
386				</tr>
387<?php
388					}
389					break;
390			}
391		}
392	} else {
393?>
394				<tr>
395					<th class="category" colspan="2">
396						<?php echo $t_question_title; ?>
397					</th>
398				</tr>
399<?php
400	}
401
402	# signal plugin event for additional fields
403	event_signal( 'EVENT_BUG_ACTIONGROUP_FORM', array( $t_event_params ) );
404
405	if( $t_bugnote ) {
406		$t_default_bugnote_view_status = config_get( 'default_bugnote_view_status' );
407		$t_bugnote_private = $t_default_bugnote_view_status == VS_PRIVATE;
408		$t_bugnote_class = $t_bugnote_private ? 'form-control bugnote-private' : 'form-control';
409
410?>
411				<tr>
412					<th class="category">
413						<?php echo lang_get( 'add_bugnote_title' ); ?>
414					</th>
415					<td>
416						<textarea name="bugnote_text" id="bugnote_text" class="<?php echo $t_bugnote_class ?>" cols="80" rows="7"></textarea>
417					</td>
418				</tr>
419<?php
420		if( access_has_project_level( config_get( 'private_bugnote_threshold' ), $t_project_id ) ) {
421?>
422				<tr>
423					<th class="category">
424						<?php echo lang_get( 'view_status' ) ?>
425					</th>
426					<td>
427<?php
428			if( access_has_project_level( config_get( 'set_view_status_threshold' ), $t_project_id ) ) {
429?>
430						<input type="checkbox" class="ace" name="private" <?php check_checked( $t_default_bugnote_view_status, VS_PRIVATE ); ?> />
431						<label class="lbl padding-6"><?php echo lang_get( 'private' ); ?></label>
432<?php
433			} else {
434				echo get_enum_element( 'view_state', $t_default_bugnote_view_status );
435			}
436?>
437					</td>
438				</tr>
439<?php
440		}
441	}
442?>
443		<tr class="spacer"></tr>
444		<?php bug_group_action_print_bug_list( $f_bug_arr ); ?>
445		<tr class="spacer"></tr>
446			</tbody>
447		</table>
448		</div>
449		</div>
450		<div class="widget-toolbox padding-8 clearfix">
451			<input type="submit" class="btn btn-primary btn-white btn-round" value="<?php echo $t_button_title ?>" />
452		</div>
453		</div>
454		</div>
455	</form>
456</div>
457</div>
458
459<?php
460bug_group_action_print_bottom();
461