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 * Manage configuration for workflow Config
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 config_api.php
29 * @uses constant_inc.php
30 * @uses current_user_api.php
31 * @uses form_api.php
32 * @uses gpc_api.php
33 * @uses helper_api.php
34 * @uses html_api.php
35 * @uses lang_api.php
36 * @uses print_api.php
37 */
38
39require_once( 'core.php' );
40require_api( 'access_api.php' );
41require_api( 'authentication_api.php' );
42require_api( 'config_api.php' );
43require_api( 'constant_inc.php' );
44require_api( 'current_user_api.php' );
45require_api( 'form_api.php' );
46require_api( 'gpc_api.php' );
47require_api( 'helper_api.php' );
48require_api( 'html_api.php' );
49require_api( 'lang_api.php' );
50require_api( 'print_api.php' );
51
52form_security_validate( 'manage_config_workflow_set' );
53
54auth_reauthenticate();
55
56/**
57 * Retrieves the value of configuration option for the project's parent
58 * (ALL_PROJECTS level if project, or file-level if all projects)
59 * @param integer $p_project Project.
60 * @param string  $p_option  Configuration option to retrieve.
61 * @return mixed configuration option value
62 */
63function config_get_parent( $p_project, $p_option ) {
64	if( $p_project == ALL_PROJECTS ) {
65		return config_get_global( $p_option );
66	} else {
67		return config_get( $p_option, null, null, ALL_PROJECTS );
68	}
69}
70
71/**
72 * Retrieves the access level needed to change the configuration option in the
73 * project's parent (ALL_PROJECTS level if project, or file-level if all projects)
74 * @param integer $p_project Project.
75 * @param string  $p_option  Configuration option to retrieve.
76 * @return integer access level
77 */
78function config_get_access_parent( $p_project, $p_option ) {
79	if( $p_project == ALL_PROJECTS ) {
80		return config_get_global( 'admin_site_threshold' );
81	} else {
82		return config_get_access( $p_option, null, ALL_PROJECTS );
83	}
84}
85
86
87$t_can_change_level = min( config_get_access( 'status_enum_workflow' ), config_get_access( 'report_bug_threshold' ), config_get_access( 'set_status_threshold' )
88		, config_get_access( 'bug_submit_status' ), config_get_access( 'bug_resolved_status_threshold' ), config_get_access( 'bug_reopen_status' ) );
89access_ensure_project_level( $t_can_change_level );
90
91$t_redirect_url = 'manage_config_workflow_page.php';
92$t_project = helper_get_current_project();
93$t_access = current_user_get_access_level();
94
95layout_page_header( lang_get( 'manage_workflow_config' ), $t_redirect_url );
96
97layout_page_begin( 'manage_overview_page.php' );
98
99# process the changes to threshold values
100$t_valid_thresholds = array(
101	'bug_submit_status',
102	'bug_resolved_status_threshold',
103	'bug_reopen_status',
104);
105
106foreach( $t_valid_thresholds as $t_threshold ) {
107	$t_access_current = config_get_access( $t_threshold );
108	if( $t_access >= $t_access_current ) {
109		$f_value = gpc_get( 'threshold_' . $t_threshold );
110		$t_value_current = config_get( $t_threshold );
111		$t_value_parent = config_get_parent( $t_project, $t_threshold );
112
113		$f_access = gpc_get( 'access_' . $t_threshold );
114		$t_access_parent = config_get_access_parent( $t_project, $t_threshold );
115
116		if( $f_value == $t_value_parent && $f_access == $t_access_parent ) {
117			# If new value is equal to parent and access has not changed
118			config_delete( $t_threshold, ALL_USERS, $t_project );
119		} else if( $f_value != $t_value_current || $f_access != $t_access_current ) {
120			# Set config if value or access have changed
121			config_set( $t_threshold, $f_value, NO_USER, $t_project, $f_access );
122		}
123	}
124}
125
126$t_enum_status = MantisEnum::getAssocArrayIndexedByValues( config_get( 'status_enum_string' ) );
127
128# process the workflow by reversing the flags to a matrix and creating the appropriate string
129if( config_get_access( 'status_enum_workflow' ) <= $t_access ) {
130	$f_value = gpc_get( 'flag', array() );
131	$f_access = gpc_get( 'workflow_access' );
132	$t_matrix = array();
133
134	foreach( $f_value as $t_transition ) {
135		list( $t_from, $t_to ) = explode( ':', $t_transition );
136		$t_matrix[$t_from][$t_to] = '';
137	}
138	$t_workflow = array();
139	foreach( $t_enum_status as $t_state => $t_label ) {
140		$t_workflow_row = '';
141		$t_default = gpc_get_int( 'default_' . $t_state );
142		if( isset( $t_matrix[$t_state] ) && isset( $t_matrix[$t_state][$t_default] ) ) {
143			$t_workflow_row .= $t_default . ':' . get_enum_element( 'status', $t_default );
144			unset( $t_matrix[$t_state][$t_default] );
145			$t_first = false;
146		} else {
147			# error default state isn't in the matrix
148			echo '<p>' . sprintf( lang_get( 'default_not_in_flow' ), get_enum_element( 'status', $t_default ), get_enum_element( 'status', $t_state ) )  . '</p>';
149			$t_first = true;
150		}
151		if( isset( $t_matrix[$t_state] ) ) {
152			foreach ( $t_matrix[$t_state] as $t_next_state => $t_junk ) {
153				if( false == $t_first ) {
154					$t_workflow_row .= ',';
155				}
156				$t_workflow_row .= $t_next_state . ':' . get_enum_element( 'status', $t_next_state );
157				$t_first = false;
158			}
159		}
160		# $t_workflow_row is allowed to be empty ''
161		$t_workflow[$t_state] = $t_workflow_row;
162	}
163
164	# Get the parent's workflow, if not set default to all transitions
165	$t_access_parent = config_get_access_parent( $t_project, 'status_enum_workflow' );
166	$t_access_current = config_get_access( 'status_enum_workflow' );
167	$t_workflow_parent = config_get_parent( $t_project, 'status_enum_workflow' );
168	if( 0 == count( $t_workflow_parent ) ) {
169		foreach( $t_enum_status as $t_status => $t_label ) {
170			$t_temp_workflow = array();
171			foreach( $t_enum_status as $t_next => $t_next_label ) {
172				if( $t_status != $t_next ) {
173					$t_temp_workflow[] = $t_next . ':' . $t_next_label;
174				}
175			}
176			$t_workflow_parent[$t_status] = implode( ',', $t_temp_workflow );
177		}
178	}
179
180	if( $t_workflow == $t_workflow_parent && $f_access == $t_access_parent ) {
181		# If new value is equal to parent and access has not changed
182		config_delete( 'status_enum_workflow', ALL_USERS, $t_project );
183	} else if( $t_workflow != config_get( 'status_enum_workflow' ) || $f_access != $t_access_current ) {
184		# Set config if value or access have changed
185		config_set( 'status_enum_workflow', $t_workflow, NO_USER, $t_project, $f_access );
186	}
187}
188
189# process the access level changes
190if( min( config_get_access( 'set_status_threshold' ), config_get_access( 'report_bug_threshold' ) ) <= $t_access ) {
191	# get changes to access level to change these values
192	$f_access = gpc_get( 'status_access' );
193	$t_access_parent = config_get_access_parent( $t_project, 'set_status_threshold' );
194	$t_access_current = config_get_access( 'set_status_threshold' );
195
196	# Build access level reference arrays (parent level and current config)
197	$t_set_parent = config_get_parent( $t_project, 'set_status_threshold' );
198	$t_set_current = config_get( 'set_status_threshold' );
199	$t_bug_submit_status = config_get( 'bug_submit_status' );
200	foreach( $t_enum_status as $t_status => $t_status_label ) {
201		if( !isset( $t_set_parent[$t_status] ) ) {
202			if( $t_bug_submit_status == $t_status && config_get_access( 'report_bug_threshold' ) <= $t_access ) {
203				$t_set_parent[$t_status] = config_get_parent( $t_project, 'report_bug_threshold' );
204			} elseif( config_get_access( 'set_status_threshold' ) <= $t_access ) {
205				$t_set_parent[$t_status] = config_get_parent( $t_project, 'update_bug_status_threshold' );
206			}
207		}
208		if( !isset( $t_set_current[$t_status] ) ) {
209			if( $t_bug_submit_status == $t_status && config_get_access( 'report_bug_threshold' ) <= $t_access ) {
210				$t_set_current[$t_status] = config_get( 'report_bug_threshold' );
211			} elseif( config_get_access( 'set_status_threshold' ) <= $t_access ) {
212				$t_set_current[$t_status] = config_get( 'update_bug_status_threshold' );
213			}
214		}
215	}
216
217	# walk through the status labels to set the status threshold
218	$t_set_new = array();
219	foreach( $t_enum_status as $t_status_id => $t_status_label ) {
220		$f_level = gpc_get_int( 'access_change_' . $t_status_id, -1 );
221		if( config_get( 'bug_submit_status' ) == $t_status_id ) {
222			# Check if input exists
223			if( $f_level > -1 ) {
224				if( $f_level != $t_set_parent[$t_status_id] ) {
225					config_set( 'report_bug_threshold', (int)$f_level, ALL_USERS, $t_project, $f_access );
226				} else {
227					config_delete( 'report_bug_threshold', ALL_USERS, $t_project );
228				}
229			}
230			unset( $t_set_parent[$t_status_id] );
231			unset( $t_set_current[$t_status_id] );
232		} else {
233			# Only process those inputs that exist, since not all access_change_<status> may have been editable.
234			if( $f_level > -1 ) {
235				$t_set_new[$t_status_id] = $f_level;
236			} else {
237				if( isset( $t_set_current[$t_status_id] ) ) {
238					$t_set_new[$t_status_id] = $t_set_current[$t_status_id];
239				}
240			}
241		}
242	}
243
244	if( $t_set_new == $t_set_parent && $f_access == $t_access_parent ) {
245		# If new value is equal to parent and access has not changed
246		config_delete( 'set_status_threshold', ALL_USERS, $t_project );
247	} else if( $t_set_new != $t_set_current || $f_access != $t_access_current ) {
248		# Set config if value or access have changed
249		config_set( 'set_status_threshold', $t_set_new, ALL_USERS, $t_project, $f_access );
250	}
251}
252
253form_security_purge( 'manage_config_workflow_set' );
254
255html_operation_successful( $t_redirect_url );
256
257layout_page_end();
258