access variable member "*" in template - perl

i have a variable
var1 = {
'*' = > {
'counter' = > {
'default' = > '0',
'description' = > 'test'
}
}
}
in perl template toolkit.
How can i access the content of '*' in the template.
[% var1.*.counter %]
does not work because of the symbol is no valid name.

You can define a variable to be equal to * within the template, and use that instead.
[% star = '*' %]
[% var1.$star.counter.description %]
But I wonder why you have to have an asterisk as a key in the first place? It would be far better to provide a sensible key at the Perl level, perhaps by writing
$vars->{var1}{star} = $vars->{var1}{'*'}
before you call the Template Toolkit.

Related

Extract email from string using Template Tookit

I'm guessing this is relatively simple, but I can't find the answer.
From a string such as '"John Doe" <email#example.com>' - how can I extract the email portion from it using Template Tookit?
An example string to parse is this:
$VAR1 = {
'date' => '2021-03-25',
'time' => '03:58:18',
'href' => 'https://example.com',
'from' => 'fezius#evrostroyserov.ru on behalf of Caroline <fezius#evrostroyserov.ru>',
'bytes' => 13620,
'pmail' => 'user#example.com',
'sender' => 'sender#example.com',
'subject' => 'Some Email Subject'
};
My code, based on #dave-cross help below where $VAR1 is the output of dumper.dump(item.from)
[% text = item.from -%]
[% IF (matches = text.match('(.*?)(\s)?+<(.*?)>')) -%]
<td>[% matches.1 %]</td>
[% ELSE -%]
<td>[% text %]</td>
[% END %]
However, it's still not matching against $VAR1
This does what you want, but it's pretty fragile and this really isn't the kind of thing that you should be doing in TT code. You should either get the data parsed outside of the template and passed into variables, or you should pass in a parsing subroutine that can be called from inside the template.
But, having given you the caveats, if you still insist this is what you want to do, then this is how you might do it:
In test.tt:
[% text = '"John Doe" <email#example.com>';
matches = text.match('"(.*?)"\s+<(.*?)>');
IF matches -%]
Name: [% matches.0 %]
Email: [% matches.1 %]
[% ELSE -%]
No match found
[% END -%]
Then, testing using tpage:
$ tpage test.tt
Name: John Doe
Email: email#example.com
But I cannot emphasise enough that you should not be doing it like this.
Update: I've used this test template to investigate your further problem.
[% item = { from => '"John Doe" <email#example.com>' };
text = item.from -%]
[% IF (matches = text.match('(.*?)(\s)?+<(.*?)>')) -%]
<td>[% matches.1 %]</td>
[% ELSE -%]
<td>[% text %]</td>
[% END %]
And running it, I get this:
$ tpage test2.tt
<td> </td>
That's what I'd expect to see for a match. You're printing matches.1. That's the second item from the matches array. And the second match group is (\s). So I'm getting the space between the name and the opening angle bracket.
You probably don't want that whitespace match in your matches array, so I'd remove the parentheses around it, to make the regex (.*?)\s*<(.*?)> (note that \s* is a simpler way to say "zero or more whitespace characters").
You can now use matches.0 to get the name and matches.1 to get the email address.
Oh, and there's no need to copy items.from into text. You can call the matches vmethod on any scalar variable, so it's probably simpler to just use:
[% matches = item.from.match(...) -%]
Did I mention that this is all a really terrible idea? :-)
Update2:
This is all going to be far easier if you give me complete, runnable code examples in the same way that I am doing for you. Any time I have to edit something in order to get an example running, we run the risk that I'm guessing incorrectly how your code works.
But, bearing that in mind, here's my latest test template:
[% item = {
'date' => '2021-03-25',
'time' => '03:58:18',
'href' => 'https://example.com',
'from' => 'fezius#evrostroyserov.ru on behalf of Caroline <fezius#evrostroyserov.ru>',
'bytes' => 13620,
'pmail' => 'user#example.com',
'sender' => 'sender#example.com',
'subject' => 'Some Email Subject'
};
text = item.from -%]
[% IF (matches = text.match('(.*?)(\s)?<(.*?)>')) -%]
<td>[% matches.2 %]</td>
[% ELSE -%]
<td>[% text %]</td>
[% END %]
I've changed the definition of item to have your full example. I've left the regex as it was before my suggestions. And (because I haven't changed the regex) I've changed the output to print matches.2 instead of matches.1.
And here's what happens:
$ tpage test3.tt
<td>fezius#evrostroyserov.ru</td>
So it works.
If yours doesn't work, then you need to identify the differences between my (working) code and your (non-working) code. I'm happy to help you identify those differences, but you have to give my your non-working example in order for me to do that.
Update3:
Again I've tried to incorporate the changes that you're talking about. But again, I've had to guess at stuff because you're not sharing complete runnable examples. And again, my code works as expected.
[% USE dumper -%]
[% item = {
'date' => '2021-03-25',
'time' => '03:58:18',
'href' => 'https://example.com',
'from' => 'fezius#evrostroyserov.ru on behalf of Caroline <fezius#evrostroyserov.ru>',
'bytes' => 13620,
'pmail' => 'user#example.com',
'sender' => 'sender#example.com',
'subject' => 'Some Email Subject'
};
-%]
[% matches = item.from.match('(.*?)(\s)?<(.*?)>') -%]
[% dumper.dump(matches) %]
And testing it:
$ tpage test4.tt
$VAR1 = [
'fezius#evrostroyserov.ru on behalf of Caroline',
' ',
'fezius#evrostroyserov.ru'
];
So that works. If you want any more help, then send a complete runnable example. If you don't do that, I won't be able to help you any more.
There's a very old (and unmaintained) module, Template::Extract, that let's you define a template, then work backward from a string that might have been produced by that template:
use Template::Extract;
use Data::Dumper;
my $obj = Template::Extract->new;
my $template = qq("[% name %]" <[% email %]>);
my $string = '"John Doe" <email#example.com>';
my $extracted = $obj->extract($template, $string);
print Dumper( $extracted );
The output is:
$VAR1 = {
'email' => 'email#example.com',
'name' => 'John Doe'
};
However, there are modules that already do this job for you and will handle many more situations
I have no idea how Template Toolkit can help you. Use Email::Address or Email::Address::XS to parse an e-mail address.

Foreach hash with Perl template toolkit

I am using Perl template toolkit for rendering my data.
This is the hash that I am passing to the template
'location' => {
'1' => {
'nmi' => 'QB13557343'
},
'2' => {
'nmi' => 'QB13559843'
},
},
and in the template I am looping this hash to get the result but its not displaying
The code in the template is:
[% FOREACH loc IN location %]
<p>NMI: [% loc.nmi %][% location.loc.nmi %]
[% END %]
I tried both loc.nmi and location.loc.nmi but not getting any result.
Any help would be greatly appreciated.
It's a hash and not an array. Try to iterate over the keys.
[% FOREACH key IN location.keys %]
<p>NMI: [% location.$key.nmi %]</p>
[% END %]

Define default value in OS field when creating new task in bugzilla

I installed bugzilla 4.4 on linux server, and finished to define all groups and products.
I also defined kinds of OS and Hardware platforms. I am wondering if it is possible do define default OS or default hardware platform for specific Product.
I coudn't find any such option in the administartion page.
Thanks
You should do the next steps:
cd ..../bugzilla-4.4/template/en/custom/bug/create/
then you have to edit this file:
vi create.html.tmpl
inside the file you have to find this peace of code:
<tr>
[% INCLUDE bug/field.html.tmpl
bug = default, field = bug_fields.op_sys, editable = 1,
value = default.op_sys %]
</tr>
replace it with this code:
<tr>
[% IF product.name == "ProductA" %]
[% INCLUDE bug/field.html.tmpl
bug = default, field = bug_fields.op_sys, editable = 1,
value = "Android" %]
[% ELSIF product.name == "ProductB" %]
[% INCLUDE bug/field.html.tmpl
bug = default, field = bug_fields.op_sys, editable = 1,
value = "iOS" %]
[% ELSE %]
[% INCLUDE bug/field.html.tmpl
bug = default, field = bug_fields.op_sys, editable = 1,
value = default.op_sys %]
[% END %]
</tr>

How can I get the next immediate tag with HTML::Tokeparser?

I'm trying to get the tags that occur immediately after a particular div tag. For e.g., I have html code
<div id="example">
<h2>Example</h2>
<p>Hello !World</p>
</div>
I'm doing the following,
while ( $tag = $stream->get_tag('div') ) {
if( $tag->[1]{id} eq 'Example' ) {
$tag = $stream->get_tag;
$tag = $stream->get_tag;
if ( $tag->[0] eq 'div' ) {
...
}
}
}
But this throws the error
Can't use string ("</h2>") as a HASH ref while "strict refs" in use
It works fine if I say
$tag = $stream->get_tag('h2');
$tag = $stream->get_tag('p');
But I can't have that because I need to get the immediate two tags and verify if they are what i expect them to be.
It would be easier to tell if you posted a runnable example program, but it looks like the problem is you didn't realize that get_tag returns both start and end tags. End tags don't have attributes. Start tags are returned as [$tag, $attr, $attrseq, $text], and end tags are returned as ["/$tag", $text].

Escape Single Quotes in Template Toolkit

Do you ever escape single quotes in template toolkit for necessary javascript handlers? If so, how do you do it.
[% SET s = "A'B'C" %]
ABC
html_entity obviously doesn't work because it only handles the double quote. So how do you do it?
I don't use the inlined event handlers -- for the same reason I refuse to use the style attribute for css. Jquery just makes it to easy to do class="foo" on the html and $('.foo').click( function () {} ), in an external .js file.
But, for the purpose of doing my best to answer this question, check out these docs on Template::Filter for the ones in core.
It seems as if you could do [% s | replace( "'", "\\'" ) %], to escape single quotes. Or you could probably write a more complex sanitizing javascript parser that permits only function calls, and make your own Template::Filter
2018 update for reference:
TT has a method for this called squote for escaping single quotes and dquote for double quotes.
[% tim = "Tim O'Reilly" %]
[% tim.squote %] # Tim O\'Reilly
Questioned link would be something like:
ABC
http://www.template-toolkit.org/docs/manual/VMethods.html#section_squote
You can try: popup('[% s | html %]').
Perl isn't my strongest language... But!
Easiest way I've found is to use the JSON module. In a module called JS.pm or something:
use JSON;
sub encode () {
my $self = shift;
my $string = shift;
$json = JSON->new->allow_nonref;
return $json->encode( $string );
}
More here: http://search.cpan.org/~makamaka/JSON-2.90/lib/JSON.pm
Then in your template:
[% use JS; %]
<script>
var escaped_string = [% JS.encode( some_template_variable ) %];
</script>
Remember to double-escape the slash in the replacement, otherwise it will be interpreted as escaping the apostrophe.
[% string.replace( "'", "\\'" ) %]