Recursive opendir(), I am getting something wrong

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
mikusan
Forum Contributor
Posts: 247
Joined: Thu May 01, 2003 1:48 pm

Recursive opendir(), I am getting something wrong

Post by mikusan »

I am trying to make a css stylesheet manager, one of the important steps to the realization of this progie is my idea to organize all stylesheets in a good directory tree. However the following script is causing me headaches. I think I am running into problems with my recursion as I somehow need to close the handler before I jump into the next subdirectory, but at the moment I cannot think of a better way, and I can't fix this one.

Thanks in advance,

Code: Select all

function parse_css ($styles_root) {
	echo($styles_root);
	if (is_dir($styles_root)) {	//If directory exist returns true

	    if ($dh = opendir($styles_root)) {		//If directory is opened return true and assign $dh to that directory

	        while (($file = readdir($dh)) != false) {		//Step through file listings
				if ( ($file != '.') && ($file != '..') && ($file != '_vti_cnf') ) {
					if (ereg ("css$", $file) )	{  // Only load .css files
						echo($file);
						$handle = fopen ($file, "r");
						$contents .= fread ($handle, filesize ($file));
						fclose ($handle);
					}
					else if (  (is_dir($file)) ) {
						parse_css($file . '/');
					}
				}
				
			}
	    closedir($dh);
	    }
	}
	return( $contents );

}
$styles_root = $CFG['path_styles'];
parse_css($styles_root);
User avatar
mikusan
Forum Contributor
Posts: 247
Joined: Thu May 01, 2003 1:48 pm

Post by mikusan »

By the way, this is the error I get when I run the script directly.

Code: Select all

/var/www/html/styles/1main.css forms.css links.css tables.css newsfeed/deafault.css
Warning: fopen(deafault.css): failed to open stream: No such file or directory in /var/www/html/styles/style.php on line 29

Warning: filesize(): Stat failed for deafault.css (errno=2 - No such file or directory) in /var/www/html/styles/style.php on line 30

Warning: fread(): supplied argument is not a valid stream resource in /var/www/html/styles/style.php on line 30

Warning: fclose(): supplied argument is not a valid stream resource in /var/www/html/styles/style.php on line 31
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

$handle = fopen ($styles_root.$file, "r");
User avatar
mikusan
Forum Contributor
Posts: 247
Joined: Thu May 01, 2003 1:48 pm

Post by mikusan »

Thanks for the reply, I tried that. To no avail, it still gives me some error.

The fact Is, that Ironically, even if I pass the $root_dir to be '/var/www/newsfeed/' I get the error.

Another weird thing is that If I name the file in newsfeed/ the same name as some other css file in the directory above it I get no errors, But, I also don't get the parsing of the css style in newsfeed/.

That's why I thought it was some handler problem. But honestly I have no idea how to parse through a directory tree otherwise.

Thanks, I know this is a bugger to solve.
hedge
Forum Contributor
Posts: 234
Joined: Fri Aug 30, 2002 10:19 am
Location: Calgary, AB, Canada

Post by hedge »

I think you need to pass the root through your recursion so that you can open the file with the entire path, otherwise it will look for it in the current directory which I don't think is changing.
User avatar
mikusan
Forum Contributor
Posts: 247
Joined: Thu May 01, 2003 1:48 pm

Post by mikusan »

Yeah, I tried that, Here is the updated code:

Code: Select all

function parse_css ($styles_root) {
	echo($styles_root);
	if (is_dir($styles_root)) {	//If directory exist returns true

	    if ($dh = opendir($styles_root)) {		//If directory is opened return true and assign $dh to that directory

	        while (($file = readdir($dh)) != false) {		//Step through file listings
				if ( ($file != '.') && ($file != '..') && ($file != '_vti_cnf') ) {
					if (ereg ("css$", $file) )	{  // Only load .css files
						echo($file);
						$handle = fopen ($styles_root . $file, "r");
						$contents .= fread ($handle, filesize ($file));
						fclose ($handle);
					}
					else if ( (is_dir($file)) ) {
						parse_css($styles_root . $file . '/');
					}
				}
				
			}
	    closedir($dh);
	    }
	}
	return( $contents );
}

$styles_root = $CFG['path_styles'];
parse_css($styles_root)
But still I get :

Code: Select all

This is the echo ($styles_root) at the beginning of the function
/var/www/html/styles/newsfeed/deafault.css
then..

Code: Select all

Warning: filesize(): Stat failed for deafault.css (errno=2 - No such file or directory) in /var/www/html/styles/style.php on line 30
I am totally lost.
redmonkey
Forum Regular
Posts: 836
Joined: Thu Dec 18, 2003 3:58 pm

Post by redmonkey »

mikusan wrote:

Code: Select all

$contents .= fread ($handle, filesize ($file));
You are requesting the file size of a non-existant file, it should be....

Code: Select all

$contents .= fread ($handle, filesize ($styles_root . $file));
You should also note that you do not assign a the results of your function to anything so you will not see any result.
hedge
Forum Contributor
Posts: 234
Joined: Fri Aug 30, 2002 10:19 am
Location: Calgary, AB, Canada

Post by hedge »

most of the probs with the code is that you aren't appending the root where you need to and doing it wrong where you are. Try this:

Code: Select all

<?php
function parse_css ($styles_root) {
  echo($styles_root);
  if (is_dir($styles_root)) {
    if ($dh = opendir($styles_root)) {
      while (($file = readdir($dh)) != false) {
        if ( ($file != '.') && ($file != '..') && ($file != '_vti_cnf') ) {
          if (ereg ("css$", $file) ) {
            echo($file);
	    $handle = fopen ($styles_root . '/' . $file, "r");
            $contents .= fread ($handle, filesize ($styles_root . '/' . $file));
            fclose ($handle);
	  }
	  else if ( (is_dir($styles_root . '/' . $file)) ) {
            parse_css($styles_root . '/' . $file);
	  }
	}				
      }
      closedir($dh);
    }
  }
  return($contents);
}

$styles_root = $CFG['path_styles'];
parse_css($styles_root)

?>
User avatar
mikusan
Forum Contributor
Posts: 247
Joined: Thu May 01, 2003 1:48 pm

Post by mikusan »

That's very strange, I thought that

Code: Select all

$file = readdir($dh)
returned the full path to the file, should have read the manual better.

The above changes really help, they fixed the errors.

On another note. Once I fixed the error I had to modify the script as I totally forgot that I was doing recursion (DOH). So for those who want to know the final solution I posted the code below.

I would like to know though, your opinion on my choice to use pass by reference as opposed to the following little modification as seen in the full code at the end:

Code: Select all

$content .= parse_css($styles_root . $file . '/', $content);

Code: Select all

function parse_css ($styles_root, &$content) {

	if (is_dir($styles_root)) {	//If directory exist returns true

	    if ($dh = opendir($styles_root)) {		//If directory is opened return true and assign $dh to that directory

	        while (($file = readdir($dh)) != false) {		//Step through file listings
				if ( ($file != '.') && ($file != '..') && ($file != '_vti_cnf') ) {
					if (ereg ("css$", $file) )	{  // Only load .css files
						$handle = fopen ($styles_root . $file, "r");
						$content .= fread ($handle, filesize ($styles_root . $file));
						fclose ($handle);
					}
					else if ( (is_dir($file)) ) {
						parse_css($styles_root . $file . '/', $content);
					}
				}
				
			}
	    closedir($dh);
	    }
	}
	return( $content );
}

$styles_root = $CFG['path_styles'];

$intro = 'This is the style.php output, do not use this like I did and just include the style.php file into your page, the time it takes to go through 5 directories is kinda repulsive.  Use it to compile a style.css file such that you get both a nice organizational structure and the speed;)'';
echo( parse_css($styles_root, $intro) );
redmonkey
Forum Regular
Posts: 836
Joined: Thu Dec 18, 2003 3:58 pm

Post by redmonkey »

I don't see any problems with passing by reference, as long as you understand what is going on then all will be good.

I note you have commented on the time taken to parse through 5 directories, how long is this taking? I have a script which I use on a regular basis which (at present) parses 480 (approx) directories with each directory having 5-10 files. The files are opened and there are then multiple regex performed on them, the data is extracted and thrown into a large array which is then used to write an HTML, XML and pipe delimted file with all the data. This particular script takes approximately six seconds to parse all the directories and files within so I wouldn't think that 5 directories would be that much of a problem (unless of course you have 2000 files in each one).
User avatar
mikusan
Forum Contributor
Posts: 247
Joined: Thu May 01, 2003 1:48 pm

Post by mikusan »

Sorry for the delayed reply, I was away for long.

Even though I am parsing through 5 directories with approx 15 files in each, the inclusion of the template file, which is done in the header of the page, actually slows the page from loading significantly.

From what I understand so far, when a page is parsed, the stylesheet that we include must be parsed as a whole before any output is generated. I am assuming that the template data is stored in some kind of temporary place.
Now, since I include a PHP file that will take the time to parse through the direcotries and then spit out the file, the page waits that the script is ready, no output is generated. Then, when it is generated, It stalls when it reads it into memory,
and only then it proceeds to parse the body of the page.

This is of course my off top of my head guess, and explanation for the slowdown caused by my script.
(My RSS feeds parser takes less time "no time", and this one has to connect to remote sources and read and parse...)
But then again, It is possible that my hosting company which let's just say does not have a good uptime and reliability record, that Is making fun of me.

As for my Passing by reference, I got confused with C programming when I did the above, That's why I was asking, I mean it worked, and you do not need the return statement,
but I was trying both methods and forgot about it ;)
I basically got confused by C's pointers, it's much easier in php lol

So for the script above, what I did is I wrote some mroe functions to make stylesheets depending on which page is loaded (now there is less weight/style) and I also parse it only when I make changes to the styles, run the script and it generates all the styles.

It's a good compromise in the end.
Post Reply