Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem with text replacement for template.

Status
Not open for further replies.

etheracideguitarist

Programmer
Sep 4, 2008
5
For my templating system I have a module which converts pre-defined 'tags' into what is supposed to be replaced by those tags. For the most part the tag is replaced by a subroutine in the search pattern and the subroutine is in charge of doing whatever it must to figure out what to print.

Code:
	open(TEMP, "$site_path/templates/template.cms"); 
	$template = do { local $/; <TEMP> };  
	close(TEMP); 
	
	$template =~ s/%%show_comments%%/&show_comments;/eg;

I have about 10 tags which are working with no problem and my template is printing everything exactly as it should. Except for the comments portion. The code above runs the subroutine show_comments and that subroutine tells the template module what to print in the place lf %%show_comments%%

Before I post the code below I will mention that partially does what it is supposed to do. But when viewing the cgi created page which uses the template, only the very first line of the flatfile database is shown.

As shown in the following code everything that is being replaced INTO the template is added to $temp and then I run a return on $temp as you will see. This works like a charm for everything else.

Code:
sub show_comments {
if (-e "$site_path/comments/$comments_number.dat") {

open(FILE,"$site_path/comments/$comments_number.dat");
	@comments = <FILE>;
	close(FILE);
foreach $comment (@comments)
{
 chomp($comment);
 ($date,$commenter,$comment_text)=split(/\|/,$comment);
$temp = qq~
<table>
<tr>
<td>$date</td><td>$commenter</td>
</tr>
<td colspan=2>
$comment_text
</td>
</tr>
</table>
<br />
~;
return ($temp)	
}
	}else{
	$temp = qq~There are currently no comments for this entry.~; return ($temp)
	}
}

This has no problem printing the "no comments" line if the .dat file doesn't exist. But again, when viewing the script only the first comment is shown. Right now I have three appropriately formatted entries in the database.

To test all of this I used it outside the scope of a template system and turned the $temp = qq~ into just print qq~ and took out the return ($temp) line, made a mini test script out of it and ran that script. It printed out all three formatted comments as it should.

I had even tried $temp .= qq~the code~; but that had an even worse effect on the cgi created page.

None of the previous tags required a soubroutine to print something within a foreach loop. Whatever the subroutine printed was printed only once. I believe that this will come up at least a couple more times throughout my program so I'd like to try to solve it. I will gladly offer credit to those that are able to offer a solution that makes this perform as it should.

I greatly appreciate any help. Please let me know if you need any clarification.
 
Whats in the $comments_number file? If you need to show multiple comments in the template file I would think you would need to use "$temp .=" instead of "$temp =" and put the return outside the "foreach" loop.

Maybe like this:

Code:
sub show_comments {
   open(FILE,"$site_path/comments/$comments_number.dat") or return "There are currently no comments for this entry.";
   my @comments = <FILE>;
   close(FILE);
   my $temp = '';
   foreach $comment (@comments) {
      chomp($comment);
      my ($date,$commenter,$comment_text)=split(/\|/,$comment);
      $temp .= qq~
<table>
<tr>
<td>$date</td><td>$commenter</td>
</tr>
<td colspan=2>
$comment_text
</td>
</tr>
</table>
<br />
~;
   }
   return ($temp)    
}

please use the code tags in the future when posting code

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Thank you.
Well any bits I left out of the code area was a short explanation of why I had what I did in the code section.

I had tried to concatenate the string as I thought that it might help out in my situation but it caused more trouble. I will show the full text of the comment module which contains three subroutines. One to post the comment form where %%comment_form%% is in the template. The second is the one about which I am posting. And the third simply saves the comments when the form is used. The problem with concatenating the string is that when the form is put where it should be. But when it replaces %%show_comments%% it will print the comment form again and then the comments.

I do thank you for the idea of putting the return outside of the foreach loop. That was the answer. And i tried that without concatenating and it posted only one. But using the code you provided above (which is what happened when I tried it myself before posting) the form and comments are put into %%show_comments%%.

Full module is below. And both the comment form and saving of comments works properly.

Code:
sub comment_form {
open (COMMENTS, "$site_path/settings/comments.dat");
$comments_on = <COMMENTS>;
close(COMMENTS);

if ($comments_on eq "on") {
$temp = qq~
<form action="$script_location" method=POST>
<input type=hidden name=action value="save_comment">
<input type=hidden name=entry value="$entry_number">
<input type=hidden name=username value="$username">
<input type=hidden name=password value="$password">
<table>
<tr>
<td>Leave A Comment</td>
</tr>
<tr>
<td align=center>
<textarea cols=35 rows=5 name="comment_text" WRAP=SOFT></textarea>
</td>
</tr>
<td align=right>
<input type=submit value="Leave Comment">
</td>
</tr>
</table>
</form>
~;
 return ($temp)
}else{
$temp = qq~&nbsp;~; return ($temp)
 }
}


sub show_comments {
open(FILE,"$site_path/comments/$comments_number.dat") or return "There are currently no comments for this entry.";
	@comments = <FILE>;
	close(FILE);
foreach $comment (@comments)
{
 chomp($comment);
 ($date,$commenter,$comment_text)=split(/\|/,$comment);
$temp .= qq~
<table>
<tr>
<td>$date</td><td>$commenter</td>
</tr>
<td colspan=2>
$comment_text
</td>
</tr>
</table>
<br />
~;
}
return ($temp)	
}


sub save_comment {

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
$correct_year = $year + 1900;
$correct_month = $mon + 1;
$date = "$correct_month/$mday/$correct_year - $hour:$min $isdt"; 

open (COMMENT, ">>$site_path/comments/$comments_number.dat");
print COMMENT "$date\|$username\|$comment_text\n";
close(COMMENT);

}

1;
 
seems very inefficient to reopen the .dat file over and over, but hard to say from looking at your code. Next time start by using "strict" and "warnings" when writing your code. When it is all working properly you can remove them.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Each .dat file is opened once to retrieve all of the comments and it is opened once per comment being saved which is once per script execution when being used to save a new comment.

I use strict. There is one cgi using all of this. It uses the template module. The template module calls upon other modules for their subroutines such as the comments module with the three different routines in it in order to keep code separated to be found more easily. I just didn't post the code to the main cgi script as my problem relates only to the comments module.

if I use:
Code:
$temp = qq~~;

Then %%show_comments%% will not include the form. But then it showed only the first line of the database and not all records.

Now with using:
Code:
$temp .= qq~~;

It does print each record out as it is supposed to but then the form which is created in &comment_form; is printed again above the comments.
 
I think if you just mess around with your code a bit you will figure out the printing problem. Maybe use seperate variables for the different parts of the output instead of $temp for all of it.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Wow. That was simple! You were correct. I went with:

Code:
$templ .= qq~~;

Instead of:

Code:
$temp .= qq~~;
[\code]

Too simple. I played around with it plenty beforehand but I wasn't 100% positive how much it relied upon using $temp.  But now it is printing out all comment and does not add a second form to the template.

Thanks a ton.  Let me know if you'd like credit and how you would like to be credited and I will add it to all documentation as I had promised.
 
No credit necessary but thanks for asking. I think you will get this sorted out, its a logic problem that just needs a bit of trial and error to get fixed.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top