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 * Mantis Configuration Report
19 * @package MantisBT
20 * @copyright Copyright 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
21 * @copyright Copyright 2002  MantisBT Team - mantisbt-dev@lists.sourceforge.net
22 * @link http://www.mantisbt.org
23 *
24 * @uses core.php
25 * @uses access_api.php
26 * @uses authentication_api.php
27 * @uses config_api.php
28 * @uses constant_inc.php
29 * @uses database_api.php
30 * @uses form_api.php
31 * @uses helper_api.php
32 * @uses html_api.php
33 * @uses lang_api.php
34 * @uses print_api.php
35 * @uses project_api.php
36 * @uses string_api.php
37 * @uses user_api.php
38 */
39
40require_once( 'core.php' );
41require_api( 'access_api.php' );
42require_api( 'authentication_api.php' );
43require_api( 'config_api.php' );
44require_api( 'constant_inc.php' );
45require_api( 'database_api.php' );
46require_api( 'form_api.php' );
47require_api( 'helper_api.php' );
48require_api( 'html_api.php' );
49require_api( 'lang_api.php' );
50require_api( 'print_api.php' );
51require_api( 'project_api.php' );
52require_api( 'string_api.php' );
53require_api( 'user_api.php' );
54
55access_ensure_global_level( config_get( 'view_configuration_threshold' ) );
56
57$t_read_write_access = access_has_global_level( config_get( 'set_configuration_threshold' ) );
58
59require_js( 'adm_config_report.js' );
60layout_page_header( lang_get( 'configuration_report' ) );
61layout_page_begin( 'manage_overview_page.php' );
62
63print_manage_menu( PAGE_CONFIG_DEFAULT );
64print_manage_config_menu( 'adm_config_report.php' );
65
66/**
67 * Ensures the given config is valid
68 * @param string $p_config Configuration name
69 * @return string|integer Config name if valid, or META_FILTER_NONE of not
70 */
71function check_config_value( $p_config ) {
72	if(    $p_config != META_FILTER_NONE
73	   && !is_blank( $p_config )
74	   && is_null( @config_get( $p_config ) )
75	) {
76		return META_FILTER_NONE;
77	}
78	return $p_config;
79}
80
81# Get filter values
82$t_filter_save          = gpc_get_bool( 'save' );
83$t_filter_default       = gpc_get_bool( 'default_filter_button', false );
84$t_filter_reset         = gpc_get_bool( 'reset_filter_button', false );
85if( $t_filter_default ) {
86	$t_filter_user_value    = ALL_USERS;
87	$t_filter_project_value = ALL_PROJECTS;
88	$t_filter_config_value  = META_FILTER_NONE;
89} else if( $t_filter_reset ) {
90	$t_filter_user_value    = META_FILTER_NONE;
91	$t_filter_project_value = META_FILTER_NONE;
92	$t_filter_config_value  = META_FILTER_NONE;
93} else {
94	$t_filter_user_value    = gpc_get_int( 'filter_user_id', ALL_USERS );
95	$t_filter_project_value = gpc_get_int( 'filter_project_id', ALL_PROJECTS );
96	$t_filter_config_value  = check_config_value( gpc_get_string( 'filter_config_id', META_FILTER_NONE ) );
97}
98
99# Manage filter's persistency through cookie
100$t_cookie_name = config_get_global( 'manage_config_cookie' );
101if( $t_filter_save ) {
102	# Save user's filter to the cookie
103	$t_cookie_string = implode(
104		':',
105		array(
106			$t_filter_user_value,
107			$t_filter_project_value,
108			$t_filter_config_value,
109		)
110	);
111	gpc_set_cookie( $t_cookie_name, $t_cookie_string, true );
112} else {
113	# Retrieve the filter from the cookie if it exists
114	$t_cookie_string = gpc_get_cookie( $t_cookie_name, null );
115
116	if( null !== $t_cookie_string ) {
117		$t_cookie_contents = explode( ':', $t_cookie_string );
118
119		$t_filter_user_value    = $t_cookie_contents[0];
120		$t_filter_project_value = $t_cookie_contents[1];
121		$t_filter_config_value  = check_config_value( $t_cookie_contents[2] );
122
123		if( $t_filter_project_value != META_FILTER_NONE && !project_exists( $t_filter_project_value ) ) {
124			$t_filter_project_value = ALL_PROJECTS;
125		}
126	}
127}
128
129# Apply filters
130
131# Get users in db having specific configs
132$t_sql = 'SELECT DISTINCT c.user_id AS config_uid, u.id, u.username, u.realname'
133		. ' FROM {config} c LEFT JOIN {user} u ON c.user_id=u.id'
134		. ' WHERE c.user_id <> :all_users ORDER BY c.user_id';
135$t_query = new DbQuery( $t_sql, array( 'all_users' => ALL_USERS ) );
136$t_users_list = array();
137$t_users_ids = array();
138$t_sort = array();
139$t_deleted_users = array();
140while( $t_row = $t_query->fetch() ) {
141	if( empty( $t_row['id'] ) ) {
142		# the user doesn't exist, deleted
143		$t_deleted_users[] = (int)$t_row['config_uid'];
144		continue;
145	}
146	$t_users_ids[] = (int)$t_row['id'];
147	$t_users_list[] = user_get_name_from_row( $t_row );
148	$t_sort[] = user_get_name_for_sorting_from_row( $t_row );
149}
150if( !empty( $t_deleted_users ) ) {
151	user_cache_array_rows( $t_deleted_users );
152	foreach( $t_deleted_users as $t_id ) {
153		$t_users_ids[] = $t_id;
154		$t_name = user_get_name( $t_id );
155		$t_users_list[] = $t_name;
156		$t_sort[] = $t_name;
157	}
158}
159if( $t_filter_user_value != META_FILTER_NONE && $t_filter_user_value != ALL_USERS ) {
160	# Make sure the filter value exists in the list
161	$t_row = user_get_row( $t_filter_user_value );
162	$t_users_ids[] = $t_filter_user_value;
163	$t_users_list[] = user_get_name_from_row( $t_row );
164	$t_sort[] = user_get_name_for_sorting_from_row( $t_row );
165}
166user_cache_array_rows( $t_users_ids );
167array_multisort( $t_sort, SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $t_users_list, $t_users_ids );
168$t_users_list = array_combine( $t_users_ids, $t_users_list );
169
170# Prepend '[any]' and 'All Users' to the list
171$t_users_list = array(
172		META_FILTER_NONE => '[' . lang_get( 'any' ) . ']',
173		ALL_USERS        => lang_get( 'all_users' ),
174	)
175	+ $t_users_list;
176
177# Get projects in db with specific configs
178$t_query = 'SELECT DISTINCT project_id, pt.name as project_name
179	FROM {config} ct
180	JOIN {project} pt ON pt.id = ct.project_id
181	WHERE project_id!=0
182	ORDER BY project_name';
183$t_result = db_query( $t_query );
184$t_projects_list[META_FILTER_NONE] = '[' . lang_get( 'any' ) . ']';
185$t_projects_list[ALL_PROJECTS] = lang_get( 'all_projects' );
186while( $t_row = db_fetch_array( $t_result ) ) {
187	/**
188	 * @var integer $v_project_id
189	 * @var string  $v_project_name
190	 */
191	extract( $t_row, EXTR_PREFIX_ALL, 'v' );
192	$t_projects_list[$v_project_id] = $v_project_name;
193}
194
195# Get config list used in db
196$t_query = 'SELECT DISTINCT config_id FROM {config} ORDER BY config_id';
197$t_result = db_query( $t_query );
198$t_configs_list[META_FILTER_NONE] = '[' . lang_get( 'any' ) . ']';
199if( $t_filter_config_value != META_FILTER_NONE ) {
200	# Make sure the filter value exists in the list
201	$t_configs_list[$t_filter_config_value] = $t_filter_config_value;
202}
203while( $t_row = db_fetch_array( $t_result ) ) {
204	/**
205	 * @var string $v_config_id
206	 */
207	extract( $t_row, EXTR_PREFIX_ALL, 'v' );
208	$t_configs_list[$v_config_id] = $v_config_id;
209}
210
211# Build config query
212$t_sql = 'SELECT config_id, user_id, project_id, type, access_reqd,'
213		. ' CASE type WHEN :complex THEN null ELSE value END AS value'
214		. ' FROM {config} WHERE 1=1';
215if( $t_filter_user_value != META_FILTER_NONE ) {
216	$t_sql .= ' AND user_id = :user_id';
217}
218if( $t_filter_project_value != META_FILTER_NONE ) {
219	$t_sql .= ' AND project_id = :project_id';
220}
221if( $t_filter_config_value != META_FILTER_NONE ) {
222	$t_sql .= ' AND config_id = :config_id';
223}
224$t_sql .= ' ORDER BY user_id, project_id, config_id ';
225$t_params = array(
226	'user_id' => $t_filter_user_value,
227	'project_id' => $t_filter_project_value,
228	'config_id' => $t_filter_config_value,
229	'complex' => CONFIG_TYPE_COMPLEX
230	);
231$t_config_query = new DbQuery( $t_sql, $t_params );
232?>
233
234<div class="col-md-12 col-xs-12">
235<div class="space-10"></div>
236
237<!-- FILTER FORM -->
238<form id="filter_form" method="post">
239	<?php # CSRF protection not required here - form does not result in modifications ?>
240		<input type="hidden" name="save" value="1" />
241
242<div class="widget-box widget-color-blue2">
243<div class="widget-header widget-header-small">
244<h4 class="widget-title lighter">
245	<?php print_icon( 'fa-filter', 'ace-icon' ); ?>
246	<?php echo lang_get( 'filters' ) ?>
247</h4>
248</div>
249
250<div class="widget-body">
251<div class="widget-main no-padding">
252	<div class="table-responsive">
253	<table class="table table-striped table-bordered table-condensed">
254		<!-- Title -->
255		<thead>
256			<tr>
257				<th>
258					<?php echo lang_get( 'username' ); ?><br />
259				</th>
260				<th>
261					<?php echo lang_get( 'project_name' ); ?><br />
262				</th>
263				<th>
264					<?php echo lang_get( 'configuration_option' ); ?><br />
265				</th>
266			</tr>
267		</thead>
268
269		<tbody>
270			<tr>
271				<td>
272					<select name="filter_user_id" class="input-sm">
273						<?php
274						print_option_list_from_array( $t_users_list, $t_filter_user_value );
275						?>
276					</select>
277				</td>
278				<td>
279					<select name="filter_project_id" class="input-sm">
280						<?php
281						print_option_list_from_array( $t_projects_list, $t_filter_project_value );
282						?>
283					</select>
284				</td>
285				<td>
286					<select name="filter_config_id" class="input-sm">
287						<?php
288						print_option_list_from_array( $t_configs_list, $t_filter_config_value );
289						?>
290					</select>
291				</td>
292			</tr>
293		</tbody>
294	</table>
295</div>
296</div>
297<div class="widget-toolbox padding-8 clearfix">
298	<div class="btn-toolbar">
299		<div class="btn-group">
300			<input name="apply_filter_button" type="submit" class="btn btn-sm btn-primary btn-white btn-round"
301				value="<?php echo lang_get( 'filter_button' )?>" />
302
303			<input name="default_filter_button" type="submit" class="btn btn-sm btn-primary btn-white btn-round"
304				value="<?php echo lang_get( 'default_filter' )?>" />
305
306			<input name="reset_filter_button" type="submit" class="btn btn-sm btn-primary btn-white btn-round"
307				value="<?php echo lang_get( 'reset_query' )?>" />
308		</div>
309	</div>
310</div>
311</div>
312</div>
313</form>
314
315
316<div class="space-10"></div>
317
318<!-- CONFIGURATIONS LIST -->
319<a id="database_configuration"></a>
320<div class="widget-box widget-color-blue2">
321<div class="widget-header widget-header-small">
322<h4 class="widget-title lighter">
323	<?php print_icon( 'fa-database', 'ace-icon' ); ?>
324	<?php echo lang_get( 'database_configuration' ) ?>
325</h4>
326</div>
327
328<div class="widget-body">
329<div class="widget-main no-padding">
330	<div class="widget-toolbox padding-8 clearfix">
331		<?php
332		$t_url_new = 'adm_config_page.php?action=' . MANAGE_CONFIG_ACTION_CREATE;
333		$t_label = lang_get( 'set_configuration_option_action_' . MANAGE_CONFIG_ACTION_CREATE );
334		print_link_button( $t_url_new, $t_label );
335
336		print_link_button(
337			'#database_configuration',
338			sprintf( lang_get( 'show_all_complex' ), config_get_type_string( CONFIG_TYPE_COMPLEX ) ),
339			'expand_all'
340		);
341		?>
342	</div>
343<div class="table-responsive sortable">
344	<table class="table table-striped table-bordered table-condensed table-hover">
345		<thead>
346			<tr>
347				<th><?php echo lang_get( 'username' ) ?></th>
348				<th><?php echo lang_get( 'project_name' ) ?></th>
349				<th><?php echo lang_get( 'configuration_option' ) ?></th>
350				<th><?php echo lang_get( 'configuration_option_type' ) ?></th>
351				<th><?php echo lang_get( 'configuration_option_value' ) ?></th>
352				<th><?php echo lang_get( 'access_level' ) ?></th>
353				<?php if( $t_read_write_access ) { ?>
354				<th class="no-sort"><?php echo lang_get( 'actions' ) ?></th>
355				<?php } ?>
356			</tr>
357		</thead>
358
359		<tbody>
360<?php
361# Pre-generate a form security token to avoid performance issues when the
362# db contains a large number of configurations
363$t_form_security_token = form_security_token( 'adm_config_delete' );
364
365while( $t_row = $t_config_query->fetch() ) {
366	/**
367	 * @var integer $v_type
368	 * @var integer $v_user_id
369	 * @var integer $v_project_id
370	 * @var string  $v_config_id
371	 * @var mixed   $v_value
372	 * @var integer $v_access_reqd
373	 */
374	extract( $t_row, EXTR_PREFIX_ALL, 'v' );
375
376	# For complex values, the content is not rendered
377	if( CONFIG_TYPE_COMPLEX == $v_type ) {
378		$t_url_params = array(
379					'user_id'       => $v_user_id,
380					'project_id'    => $v_project_id,
381					'config_option' => $v_config_id,
382					'action'        => MANAGE_CONFIG_ACTION_VIEW
383				);
384		$t_url_view = helper_url_combine( 'adm_config_page.php', http_build_query( $t_url_params ) );
385		$t_html_value = '<div class="adm_config_expand" data-config_id="' . $v_config_id . '"'
386				. ' data-project_id="' . $v_project_id . '" data-user_id="' . $v_user_id . '">'
387				. '<span class ="expand_show"><a href="' . $t_url_view . '" class="toggle small">[' . lang_get( 'show_content' ) . ']</a></span>'
388				. '<span class ="expand_hide hidden"><a href="#" class="toggle small">[' . lang_get( 'hide_content' ) . ']</a></span>'
389				. '<div class="expand_content"></div>'
390				. '</div>';
391	} else {
392		$t_html_value = config_get_value_as_string( $v_type, $v_value );
393	}
394
395?>
396<!-- Repeated Info Rows -->
397			<tr class="visible-on-hover-toggle">
398				<td>
399					<?php echo ($v_user_id == 0) ? lang_get( 'all_users' ) : string_display_line( user_get_name( $v_user_id ) ) ?>
400				</td>
401				<td><?php echo string_display_line( project_get_name( $v_project_id, false ) ) ?></td>
402				<td><?php echo string_display_line( $v_config_id ) ?></td>
403				<td><?php echo string_display_line( config_get_type_string( $v_type ) ) ?></td>
404				<td style="overflow-x:auto;"><?php echo $t_html_value ?></td>
405				<td><?php echo get_enum_element( 'access_levels', $v_access_reqd ) ?></td>
406<?php
407	if( $t_read_write_access ) {
408?>
409<td class="center">
410	<div class="btn-group inline visible-on-hover">
411<?php
412		if( config_can_delete( $v_config_id ) ) {
413			$t_action_params = array(
414					'user_id'       => $v_user_id,
415					'project_id'    => $v_project_id,
416					'config_option' => $v_config_id,
417				);
418
419			# Update button
420			$t_action_params['action'] = MANAGE_CONFIG_ACTION_EDIT;
421			$t_url_edit = helper_url_combine( 'adm_config_page.php', http_build_query( $t_action_params ) );
422			echo '<div class="pull-left">';
423			print_link_button( $t_url_edit, lang_get( 'edit' ), 'btn-xs' );
424			echo '</div>';
425
426			# Clone button
427			echo '<div class="pull-left">';
428			$t_action_params['action'] = MANAGE_CONFIG_ACTION_CLONE;
429			$t_url_clone = helper_url_combine( 'adm_config_page.php', http_build_query( $t_action_params ) );
430			print_link_button( $t_url_clone, lang_get( 'create_child_bug_button' ), 'btn-xs' );
431			echo '</div>';
432
433			# Delete button
434			echo '<div class="pull-left">';
435			print_form_button(
436				'adm_config_delete.php',
437				lang_get( 'delete' ),
438				array(
439					'user_id'       => $v_user_id,
440					'project_id'    => $v_project_id,
441					'config_option' => $v_config_id,
442				),
443				$t_form_security_token
444			);
445			echo '</div>';
446		} else {
447			echo '&#160;';
448		}
449?>
450	</div>
451				</td>
452<?php
453	} # end if config_can_delete
454?>
455			</tr>
456<?php
457} # end while loop
458?>
459		</tbody>
460	</table>
461</div>
462</div>
463</div>
464</div>
465
466</div>
467
468<?php
469layout_page_end();
470