Hi all,

Ugh. I'm not a programmer by any means, but I've found myself needing to customize one of the modules, and I'm having a hard time controlling a 'foreach' loop using the node arrays. The module I'm working reads the contents of a folder and builds an array containing the names of the image files in a folder. I'm trying to build 2 'foreach' statements, one which counts the number of files and writes a line of html for each item, and the second loop outputs a few lines of html for each image in the array and inserts the image filename into placeholders in that html.

I've installed the devel module, so I can see the variable/array dump for my node, but can't figure out how to properly get the image count and names. I guess what I'm looking for is an understanding of what to put in the 'foreach' brackets in order to loop through the variables in the [images] array (??)

This is the code generated by the devel module:


content

Array
(
    [body] => Array
        (
            [#value] => </p>

            [#weight] => 0
        )

    [eti_beef] => Array
        (
            [#type] => eti_beef
            [#attributes] => Array
                (
                    [class] => eti_beef align-full location-above
                    [id] => eti_beef-4
                )

            [#eti_beef] => Array
                (
                    [settings] => Array
                        (
                            [eti_beef-4] => Array
                                (
                                    [images] => Array
                                        (
                                            [1] => Array
                                                (
                                                    [src] => http://myservername.com/files/eti_beef/beef_image01.gif
                                                    [title] => beef_image01.gif
                                                )

                                            [2] => Array
                                                (
                                                    [src] => http://myservername.com/files/eti_beef/beef_image02.gif
                                                    [title] => beef_image02.gif
                                                )

                                        )

                                    [total] => 2
                                    [current] => 1
                                )

                        )

                    [status] => Array
                        (
                            [current] => 1
                            [total] => 2
                            [previous] => 2
                            [next] => 2
                        )

                    [url] => node/4
                    [title] => beef_image01.gif
                    [image] => http://myservername.com/files/eti_beef/beef_image01.gif
                )

            [#weight] => -5
        )

)


For example, here is the first loop (I know the $eti_beef[images'] part is wrong, but I don't know what to do to loop through the [images] variables:

	// start loop
       foreach ( $eti_beef['images'] as $imagename) {	
  	
 		$key = $key + 1;
		if ($key < 10) { $key = "0".$key; }
		$output .= "<li><a class='navi' href='#'><span>".$key." - Image name:".$imagename."</span></a></li>\n"; 
	}
	$key = 0;
	// end loop

I think it's probably a simple solution, and I just don't have the PHP knowlege to figure it out... Any help would be appreciated.

Tx!

Ira

Comments

nevets’s picture

So this example is more of a starting point that a full blow solution

<?php
$dir = "the directory you want to read

$image_count = 0;   // The number of images found
$images = array();   // The information about each image

// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
	if ($dh = opendir($dir)) {
		while (($file = readdir($dh)) !== false) {
			if ( filetype($dir . $file) == 'file' ) {
				$filename_parts = pathinfo($dir . $file);
				switch ( $filename_parts['extension'] ) {
				case 'jpeg':  // The set of possble extenstions for images
				case 'png':
				case 'gif':		// You might want to extend
					// The heart of you question - part 1 - have an image file
					$image_count++;		// Increment the count of images
					if ( $count < 10 ) {
						$key = '0' . $count;
					}
					else {
						$key = $count;
					}
					// Store information about the image
					$images[] = "<a class='navi' href='#'><span>".$key." - Image name:".$dir . $file."</span></a>"; 
					// End part 1
					break;
				}
			}
		}
		closedir($dh);
		// The heart of you question - part 2 - output the information
		if ( $image_count > 0 ) {
			$output = theme('item_list', $images);
		}
		$output .= "<p>$image_count images found</p>";
	}
}
?> 
ira42’s picture

Thanks for the quick response. Your code is very clear, and I see how it would work (I'm learing. slowly.). To clarify a bit, the existing module that I'm modifying is the Slideshow module, so the code to read the folder contents and generate the arrays already exists. I think my main concern is how to reference the existing values (as outputed in the devel results above) within the existing [images] array, within a completely seperate function in the code.

I've been experimenting a bit, and for the first part, the following code seems to be working for me:


	// start loop
  foreach ( array($eti_beef['settings'], 'setting') as $image) {	
  	
 		$key = $key + 1;
		if ($key < 10) { $key = "0".$key; }
		$output .= "<li><a class='navi' href='#'><span>".$key."</span></a></li>\n"; 
	}
	$key = 0;
	// end loop

which outputs the following (which is what I wanted, but could just be a coincidence!):

<li><a class='navi' href='#'><span>01</span></a></li>
<li><a class='navi' href='#'><span>02</span></a></li>

Lovely. However, the second 'foreach' call within that function isn't quite working. The code is:

  foreach ( array($eti_beef['settings'], 'setting') as $image => $value) {	
  			
		$output .= "				<div class='slide'>\n";
		$output .= "					<div class='slide-inner'>\n";
		$output .= "						<a href='#'><img src='".$image."' /></a>\n";
		$output .= "					</div>\n";
		$output .= "				</div>\n";
		

which returns:

<div class='slide'>
					<div class='slide-inner'>

						<a href='#'><img src='0' /></a>
					</div>
				</div>
				<div class='slide'>
					<div class='slide-inner'>
						<a href='#'><img src='1' /></a>
					</div>
				</div>

I know it's wrooooong, but can't find a way to loop through the [images] array in order to loop through the [title] values....

Anyhoo, a long shot, but maybe you might see what I'm trying to do and know what syntax to use in the foreach loop.

Thanks again for your help and patience.

Ira

nevets’s picture

When you have a foreach loop like this

foreach ( array($eti_beef['settings'], 'setting') as $image => $value) { 

the as $image => $value tells it to place the array index in the first part ($image in this case) and the array element in the second part ($value in this case). Since you do not seem to need the index you could just use

foreach ( array($eti_beef['settings'], 'setting') as $image ) { 

which walks through each element of the array.

A bigger issue, you loop is not really dealing with filename (images) as you are constructing you own array array($eti_beef['settings'], 'setting') which has two elements, the value of $eti_beef['settings'] and the constant 'setting'. This is also why your first loop outputs two elements.

As for getting the titles, with out a better understanding of what you are modify that would be hard. I looked at slideshow.module and it does not contain a variable $eti_beef so I am guessing this is one you added. If you can provide a function and linenumber for were you are making the changes I can possibly help.

ira42’s picture

Yup, I figured that the two elements returned in the first part was just a coincindence!

Because I'm working with a copy of the Slideshow module, i renamed the copy (and all references within the code) from 'Slideshow/slideshow/SLIDESHOW' to 'Eti_beef/eti_beef/ETI_BEEF', to make sure that the two modules weren't conflicting in any way.

The part of the Slideshow code that I'm trying to modify is the last bit, starting at line 558 ("function theme_slideshow($element)...."). Rather than have it display just one slide at a time, with the next/current/previous links, I'd like it to loop through all of the attached images and output all the divs at once.

Here's the code that I've replaced from 558 on:

function theme_eti_beef($element) {
  $eti_beef = $element['#eti_beef'];
  $status = $element['#eti_beef']['status'];
  drupal_add_js(drupal_get_path('module', 'eti_beef') .'/eti_beef.js');
  
  drupal_add_css(drupal_get_path('module', 'eti_beef') .'/eti_beef.css');
  drupal_add_js(array('eti_beef' => $eti_beef['settings']), 'setting');

	// NEW CODE START
	
	$output = "		<style type=\"text/css\" media=\"screen\">\n";
	$output .= "		#fpss-container {width:500px;}\n";
	$output .= "		#fpss-slider, #slide-loading, .slide {width:500px;height:205px;}\n";
	$output .= "		#slide-outer, #slide-outer .slide-inner {height:205px;}\n";
	$output .= "	</style>\n";
	
	
	$output .= "<div id='fpss-container' >\n";
	$output .= "	<div id='fpss-slider'>\n";
	$output .= "		<div id='slide-loading'></div>\n";
	$output .= "		<div id='navi-outer'>\n";
	$output .= "      		<div id='navi-outer-l'><span class='headline'>headline story</span>\n";
	$output .= "        		<div id='navi-outer-r'>\n";
	$output .= "          			<div class='ul_container'>\n";
	$output .= "            		<ul>\n";
	$output .= "              		<li class='noimages'></li>\n";
	
	// start loop
  foreach ( array($eti_beef['settings'], 'setting') as $image) {	
  	
 		$key = $key + 1;
		if ($key < 10) { $key = "0".$key; }
		$output .= "<li><a class='navi' href='#'><span>".$key."</span></a></li>\n";
		$output .= ''; 
	}
	$key = 0;
	// end loop

	$output .= "					<li class='noimages'><a href='#play/pause' onclick='playButtonClicked();return false;' id='playButton' class=''></a></li>\n";
	$output .= "					</ul>\n";
	$output .= "					</div>\n";
	$output .= "				</div>\n";
	$output .= "			</div>\n";
	$output .= "		</div>\n";
	$output .= "		<div id='slide-wrapper'>\n";
	$output .= "			<div id='slide-outer'>\n";
	

	
	// start loop
  foreach ( array($images) as $image) {	
  			
		$output .= "				<div class='slide'>\n";
		$output .= "					<div class='slide-inner'>\n";
		$output .= "						<a href='#'><img src='".$image."' /></a>\n";
		$output .= "					</div>\n";
		$output .= "				</div>\n";
		
	} // end loop	
		
	$output .= "			</div>\n";
	$output .= "		</div>\n";
	$output .= "	</div>\n";
	$output .= "</div>\n";
		
		
	
	// NEW CODE END

  return $output;
}

I know that "$eti_beef['settings']), 'setting'" is not correct. The only reason I used it is because line 564 has the following line:

  drupal_add_js(array('slideshow' => $slideshow['settings']), 'setting');

which seems to write the image filenames to the javascript section in the template's head section, but I don't get how it works.

Dunno, maybe I should scrap the idea of reusing the Slideshow module and try to make one from scratch.

Ira

nevets’s picture

The variable $slideshow/$eti_beef contains an element called 'settings' which is also an array and one of it's elements is called 'images' which is also an array which contains the information you want. So looking at just the loops, change the first one like this

 // start loop
// Get the array of images
$image_set = $eti_beef['settings']['images'];
 foreach ( $image_set as $key => $image) {
$display_key = $key;
if ($display_key < 10) {
  $display_key = "0".$display_key;
}
$output .= "<li><a class='navi' href='#'><span>".$display_key."</span></a></li>\n";
$output .= '';
}
$key = 0;
// end loop

Note the loop has been changed to use the key value set when building the array of images.
For the second loop the change would look something like

 // start loop
  foreach ( $image_set as $image) {
 
$output .= " <div class='slide'>\n";
$output .= " <div class='slide-inner'>\n";
$output .= " <a href='#'><img src='".$image['src']."' /></a>\n";
$output .= " </div>\n";
$output .= " </div>\n";

} // end loop 

If you want to use the title in the loop it is available as $image['title']

ira42’s picture

Much abliged! The code makes sense, but it still isn't working for me. :(

Drupal is spitting out the following errors from both of the 'foreach' lines:

"warning: Invalid argument supplied for foreach() in ..."

I've tried adding echo ($image_set); before starting the loop, at it displays as empty as well.

If you have any other ideas, please let me know. tx!!

Ira

ira42’s picture

Oh man. Ok, I looked at the Devel output again, and my structure is actually [settings]['eti_beef-4']['images'].

So I changed the line to read:

   $image_set = $eti_beef['settings']['eti_beef-4']['images'];

and it works beautifully! Thanks again.

Ira

timnorman’s picture

I'm new to PHP and know the basics. I pretty well understand the entire issue being discussed, but what does this line do in your examples?

$key = '0' . $count;

I see it setting $key equal to '0' but what does the . $count add to it? Does that append the value of $count to the zero?

Thanks in advance!

nevets’s picture

In the context of the logic it makes all keys two digits (assuming we never reach 100). So '1' becomes '01', 2 becomes '02', etc.

pcs305’s picture

I woulds like to keep track of this node!
I'm writing a module to list .asm and .cob source code files.
This code is a lot better than mine.
Thanks

renamixtech’s picture

Thank you nevets. Your well written code made my day :)