Page 1 of 1

Strange problem with recursive function (don't be scared)

Posted: Sat Dec 22, 2007 5:32 pm
by mjfernandez
Hey all.

I have a 2d array with associative information, and I pass it through a recursive function to make it into a 3d array.
The 3d array is then passed to a function which builds an html form component.
It works when I put the code in a test file, but I am trying to modify another open source php software package to include my select list.

Here is the live test page:
http://129.7.203.157/smsl/testing.php
http://129.7.203.157/smsl/testing.phps

Here is my code...

Code: Select all

class publications
{
	var $debugi;
	var $table_people = 'people';
	var $table_profiles = 'profiles';
	var $table_subjects = 'subjects';
	var $table_files = 'files';
	var $bgcolor = array('#eee','#eef','#eee','#eef','#eee','#eef');
	var $editor_url = 'category_edit.php';
	public $db;

	function __construct()
	{
		// Find out about global debug mode, 
		global $debug;
		// copy status to internal debug mode
		$this->debugi = $debug;

		$this->db = &new MySqlDB;
		$this->db->connect();
		
		// Initialization
		if ($this->debugi>=1) print "fetch.construct<br />\n";
		

	}
	
	function fetch_categories_inline() {
		$query = "SELECT * FROM `$this->table_subjects` ORDER BY priority desc, subj_name asc";
		$result = $this->db->query($query);
		while ($row = $this->db->fetch_array($result)) {
			$return_array[] = $row;
		}
		return $return_array;
	}



	function fetch_category_tree ($list, $start="0", $level="0") {

		$existed = 0;
		foreach ($list as $key=>$val) {
			if ($val[child_of] == $start) {

				$sub_categories = $this->fetch_category_tree($list,$val[sid],( $level + 1));
				$tree_branch[] = array($val[sid],($level),$val[subj_name],$sub_categories);
			}
			$existed = 1;
		}
		if ($existed == 0)
			return 0;
		else
			return $tree_branch;
	}

	function build_form_select_list_from_category_tree ($tree, $outermost=0) {
		if ($outermost==1) 
			$return_code = "<ul class=\"smsl\">";
		//$return_code = "";
		foreach ($tree as $no => $ar) {
		$return_code .= "\n<li class=\"smsl\" style=\"padding-left: "
			.(($ar[1]+1)*10)."px;\"><label for=\"pub_"
			.$ar[0]."\" class=\"smsl\"><input type=\"checkbox\" name=\"pub_"
			.$ar[0]."\" id=\"pub_".$ar[0]."\">".$ar[2]."</label></li>";
			if ($ar[3] != 0) {
				$return_code .= $this->build_form_select_list_from_category_tree($ar[3])."\n\t</div>";	
			} 
		}		
		if ($outermost==1) 
			$return_code .= "</ul>";
		return $return_code;
	}
	


	
	
}
Here is my code inside the other program:

Code: Select all

function generateBibtexForm($bibtex, $localfile)
{
	global $MAN, $OPT, $bibtexTypes, $file_dir;

	print "<table>";
	print "<tr>";
	print "<td> <strong> entry type <strong> </td>";
	print "<td>";
	print "<select name=\"bibtexEntryType\" onchange=\"bibtexform.submit();\">";
	foreach ($bibtexTypes as $name)
	{
		print "<option value=\"".$name[0]."\"";
		if (array_key_exists('bibtexEntryType', $bibtex)&& ($name[0] == $bibtex['bibtexEntryType']))
		 	print " selected >".$name[0];
		else print ">".$name[0];
		print "</option>\n";
	}
	print "</select>";
	print "</td>";
	print "</tr>";
	// MJF 2007-12-20
	print "<tr>";
	print "<td> <strong> categories </strong> <br/><em style=\"font-size: small;\">Categories must be added in the SMSL Control Panel.</em></td>";
	print "<td>";
	
	print<<<END
		  <style type="text/css">
		   ul.smsl { height: 200px; overflow: auto; width: 200px; border: 1px solid #000; 
		   list-style-type: none; margin: 0; padding: 0; overflow-x: hidden; }
		   li.smsl { margin: 0; padding: 0; }
		   label.smsl { display: block; color: WindowText; background-color: Window; margin: 0; padding: 0; width: 100%; }
		   label.smsl:hover { background-color: Highlight; color: HighlightText; }
		  </style>
END;
/*
print "<pre>";
print_r($pub->fetch_category_tree($pub->fetch_categories_inline()));
print "</pre>";
*/

	require_once('../smsl/smsl_db.inc.php');
	require_once('../smsl/smsl_forms.inc.php');
	require_once('../smsl/smsl_init.inc.php');
	require_once('../smsl/concerned_uid.inc.php');

	$pub = new publications;

	print $pub->build_form_select_list_from_category_tree($pub->fetch_category_tree($pub->fetch_categories_inline()),1);
 
	print "</td>";
	print "</tr>";
	// /MJF

	$fields = $bibtexTypes[$bibtex['bibtexEntryType']];
	generateTableForm($fields[1], $bibtex, "Edit");
        print "<tr><td><strong>Upload</strong></td>
		  	 <td>
			 <input type=\"file\" name=\"fileupload\" value=\"".$localfile."\">";
	print "</td></tr>";
	print "</table>";
}
So, the same code as the test script is used here, but these are the results:
http://129.7.203.157/smsl/messed.jpg
Notice how short the list is! It only includes the first-level array items.

I have tracked it down to this part of my code in the publications class returning zero:

Code: Select all

$sub_categories = $this->fetch_category_tree($list,$val[sid],( $level + 1));
But I have no idea why this would return zero when called by the big program, and then work perfectly fine (and return the recursive output) when called from my testing.php script.

I think the problem might have something to do with the visibility of the $pub object, but I am not sure. Does anyone know why this is happening?

Posted: Sat Dec 22, 2007 6:23 pm
by s.dot
Shouldn't you be array_merge()ing the current array with the results from the recursive function?

Code: Select all

$sub_categories = $this->fetch_category_tree($list,$val[sid],( $level + 1));
:arrow:

Code: Select all

$sub_categories = array_merge($sub_categories, $this->fetch_category_tree($list,$val[sid],( $level + 1)));
Also, you can use PHP5's built in DirectoryIterator or RecursiveDirectoryIterator objects

Posted: Sun Dec 23, 2007 12:33 am
by mjfernandez
scottayy wrote:Shouldn't you be array_merge()ing the current array with the results from the recursive function?

Code: Select all

$sub_categories = $this->fetch_category_tree($list,$val[sid],( $level + 1));
:arrow:

Code: Select all

$sub_categories = array_merge($sub_categories, $this->fetch_category_tree($list,$val[sid],( $level + 1)));
Also, you can use PHP5's built in DirectoryIterator or RecursiveDirectoryIterator objects
Thank you for responding, but no, if you look carefully at the rest of the function, you will see that $sub_categories is just a temporary variable that's reset each time the function runs. Its contents should be different each time. Each time the loop iterates, if subcategories are found, then they are put in this variable and it is appended to that iteration's return data.

What would be different about calling my code from within another php script versus calling it in a simple php file?

Posted: Thu Dec 27, 2007 5:24 am
by mjfernandez
Does anyone know what the problem could be?

I am still working on it.