View Issue Details

IDProjectCategoryView StatusLast Update
0013298mantisbtpreferencespublic2014-09-23 18:05
Reporterjspezeski Assigned Todregad  
PrioritylowSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Product Version1.2.7 
Target Version1.2.13Fixed in Version1.2.13 
Summary0013298: commas and multi-dimensional arrays in adm_config_set
Description

This TODO was in adm_config_set.php

TODO: allow multi-dimensional arrays, allow commas and => within strings

I believe I've taken care of the commas and multi-dimensional arrays.

Tagspatch
Attached Files
config_set_todo.patch (3,855 bytes)   
--- adm_config_set.php	Tue Apr 05 11:24:17 2011
+++ adm_config_set.php	Thu Sep 08 15:22:13 2011
@@ -85,34 +85,104 @@
 		# TODO: allow multi-dimensional arrays, allow commas and => within strings
 		$t_full_string = trim( $f_value );
 		if ( preg_match('/array[\s]*\((.*)\)/s', $t_full_string, $t_match ) === 1 ) {
-			// we have an array here
-			$t_values = explode( ',', trim( $t_match[1] ) );
+			$t_value=prepare_array_recursive($t_match);
+		} else {
+			// scalar value
+			$t_value = constant_replace( trim( $t_full_string ) );
+		}
+	}
+
+	config_set( $f_config_option, $t_value, $f_user_id, $f_project_id );
+
+	form_security_purge( 'adm_config_set' );
+
+	print_successful_redirect( 'adm_config_report.php' );
+
+	/**
+	 * Helper function to support multi-dimensional arrays
+	 */
+	function prepare_array_recursive ($p_array) {
+		$t_match = $p_array;
+		// separate the string into array elements
+		$t_values = special_split($t_match[1]);
+
 			foreach ( $t_values as $key => $value ) {
 				if ( !trim( $value ) ) {
 					continue;
 				}
-				$t_split = explode( '=>', $value, 2 );
+			$t_split = explode( '/=>/', $value, 2 );
 				if ( count( $t_split ) == 2 ) {
 					// associative array
-					$t_new_key = constant_replace( trim( $t_split[0], " \t\n\r\0\x0B\"'" ) );
+				if ( preg_match('/array[\s]*\((.*)\)/s', $t_split[1], $t_match ) === 1 ) {
+					// nested array
+					$t_new_value=prepare_array_recursive($t_match);
+				} 
+				else {
+					// regular element
 					$t_new_value = constant_replace( trim( $t_split[1], " \t\n\r\0\x0B\"'" ) );
+				}
+				$t_new_key = constant_replace( trim( $t_split[0], " \t\n\r\0\x0B\"'" ) );
 					$t_value[ $t_new_key ] = $t_new_value;
 				} else {
 					// regular array
-					$t_value[ $key ] = constant_replace( trim( $value, " \t\n\r\0\x0B\"'" ) );
+				if ( preg_match('/array[\s]*\((.*)\)/s', $value, $t_match ) === 1 ) {
+					// nested array
+					$t_new_value=prepare_array_recursive($t_match);
+				} else {
+					// regular element
+					$t_new_value = constant_replace( trim($value, " \t\n\r\0\x0B\"'" ) );
 				}
+				$t_value[ $key ] = $t_new_value;
 			}
-		} else {
-			// scalar value
-			$t_value = constant_replace( trim( $t_full_string ) );
 		}
+		return $t_value;
 	}
 
-	config_set( $f_config_option, $t_value, $f_user_id, $f_project_id );
-
-	form_security_purge( 'adm_config_set' );
+	/**
+	 * Split by commas, but ignore commas that are within quotes or parenthesis.
+	 * Ignoring commas within parenthesis helps allow for multi-dimensional arrays.
+	 */
+	function special_split ($p_string) {
+		$t_values=array();
+		$t_array_element = "";
+		$t_paren_level = 0;
+		$t_inside_quote = False;
+		$t_escape_next = False;
 
-	print_successful_redirect( 'adm_config_report.php' );
+		foreach (str_split(trim($p_string)) as $character) {
+			if ($t_escape_next) {
+				$t_array_element .= $character;
+				$t_escape_next= False;
+			} else
+			if ($character == "," && $t_paren_level==0 && !$t_inside_quote) {
+				array_push($t_values,$t_array_element);
+				$t_array_element = "";
+			} 
+			else {
+				if ($character == "(" && !$t_inside_quote) {
+					$t_paren_level ++;
+				} else
+				if ($character == ")" && !$t_inside_quote) {
+					$t_paren_level --;
+				} else
+				if ($character == "'") {
+					$t_inside_quote = !$t_inside_quote;
+				} else
+				// escape character
+				if ($character == "\\") {
+					$t_escape_next = True;
+					// keep the escape if the string will be going through another recursion
+					if ($t_paren_level>0) {
+						$t_array_element .= $character;
+					}
+					continue;
+				}
+				$t_array_element .= $character;
+			}
+		}
+		array_push($t_values,$t_array_element);
+		return $t_values;
+	}
 
 
 	/**
config_set_todo.patch (3,855 bytes)   

Relationships

related to 0011166 closeddhx new configuration option of 'complex' type is created with string type 
related to 0015721 closedgrangeway Functionality to consider porting to master-2.0.x 
has duplicate 0012491 closedatrol It's not possible to store complex config ararys which elements contains commas 
related to 0013382 closeddregad Make configuration options editable in adm_config_report 
related to 0014559 closeddregad Adding filter for "Configuration report" 
related to 0016931 closeddregad PHPUnit tests for admin config functions 
related to 0016932 closeddregad Move functions defined in adm_config_set.php to a core API 

Activities

rombert

rombert

2011-10-15 06:39

reporter   ~0029970

Thank you for the report and suggested fix. Would you consider submitting pull requests for this functionality? This would greatly increase the speed of including these changes in MantisBT.

Ideally you would submit pull requests for both the master and master-1.2.x branches at https://github.com/mantisbt/mantisbt .

dregad

dregad

2012-12-28 19:02

developer   ~0034636

Work in progress available for testing: https://github.com/dregad/mantisbt/tree/manage-config

I think there are still a few issues with some corner cases (e.g. the parser matches array(xxx)=>array(xxx) which is not valid)

Testing and feedback would be greatly appreciated.

dregad

dregad

2013-01-02 17:48

developer   ~0034681

atrol reported an issue with this patch 0014559:0034671:

Editing of complex values (for example view_issues_page_columns) is not longer possible. All values are lost, you get only array ()

I'll push a commit shortly, that should fix this problem.

atrol

atrol

2013-01-03 04:25

developer   ~0034685

I'll push a commit shortly, that should fix this problem.
Do you mean this one?
https://github.com/dregad/mantisbt/commit/b2d315bc2e6d6d565057c3d541347e8e13c3187e
If so, it's not fixed.

dregad

dregad

2013-01-03 07:51

developer   ~0034688

Sorry about that, it was a bit late last night when I finished, and I only ran a quick series of tests, none of which had whitespace around the '=>'.

The regex did not take this into consideration and as a result what should have been interpreted as an associative array element, was wrongly detected as a string.

Just pushed another fix, please try again.

atrol

atrol

2013-01-03 09:47

developer   ~0034691

Works now, I tested nothing more than view_issues_page_columns and status_enum_workflow.

grangeway

grangeway

2013-04-05 17:56

reporter   ~0036076

Marking as 'acknowledged' not resolved/closed to track that change gets ported to master-2.0.x branch

Related Changesets

MantisBT: master-1.2.x efb8b6b8

2011-09-09 10:25

dregad


Details Diff
Support for multi-dimentional arrays in admin_config_set.php

This commit adds support for multi-dimentional arrays, as well as
correct handling of commas and '=>' within strings.

This is based on work by jspezeski; the original code was modified to
align with MantisBT coding guidelines, simplification of the recursive
function and fixing a couple of errors in regex.

Fixes 0013298
Affected Issues
0013298
mod - adm_config_set.php Diff File

MantisBT: master 8b98640d

2011-09-09 10:25

dregad


Details Diff
Support for multi-dimentional arrays in admin_config_set.php

This commit adds support for multi-dimentional arrays, as well as
correct handling of commas and '=>' within strings.

This is based on work by jspezeski; the original code was modified to
align with MantisBT coding guidelines, simplification of the recursive
function and fixing a couple of errors in regex.

Fixes 0013298
Affected Issues
0013298
mod - adm_config_set.php Diff File

MantisBT: master-1.2.x d000c4d7

2013-01-09 08:37

dregad


Details Diff
admin_config_set: Revised process_complex_value() function

The new code features an improved regex, which deals more efficiently
with the parsing of multi-dimensional and associative arrays.

Regex are defined as static variables for better performance with
repeated and recursive calls

Known issue: an invalid definition like 'array(array(1,2)=>array(3,4))'
is not properly parsed.

Fixes 0013298
Affected Issues
0013298
mod - adm_config_set.php Diff File

MantisBT: master 0719f32d

2013-01-09 08:37

dregad


Details Diff
admin_config_set: Revised process_complex_value() function

The new code features an improved regex, which deals more efficiently
with the parsing of multi-dimensional and associative arrays.

Regex are defined as static variables for better performance with
repeated and recursive calls

Known issue: an invalid definition like 'array(array(1,2)=>array(3,4))'
is not properly parsed.

Fixes 0013298
Affected Issues
0013298
mod - adm_config_set.php Diff File