How to use custom macros outside a template?

Notice: This thread is very old.
richard
Member | 60
+
0
-

I was trying to use custom macros outside templates:

<?php
$string = "this is {hello} macro";
$parser = new Nette\Latte\Parser;
$macroSet = new Nette\Latte\Macros\MacroSet($parser);
$macroSet->addMacro(
    'hello',
    'return "Hello World";'
    );
$parser->addMacro(
    'hello',$macroSet
    );
$parsedString = $parser->parse($string);
echo $parsedString;
?>

but this comes out:
this is <?php return "Hello World"; ?> macro

How can I achieve ‘this is Hello World macro’?

Last edited by richard (2011-08-30 19:44)

HosipLan
Moderator | 4668
+
0
-

Can you tell me, why you can't use template?

richard
Member | 60
+
0
-

The text will not be displayed, just saved or processed further.

HosipLan
Moderator | 4668
+
0
-

Template have method ->save(), which can be used to saving output into file.

redhead
Member | 1313
+
0
-

or use

$string = (string) $template;

to get it as a string.

richard
Member | 60
+
0
-

Hello, string casting does not help as it does not execute a script in it.

This does the trick:

<?php
$parsedString = eval("?>".(string)$parser->parse($string));
?>

I do not know yet if I go for saving template into the file as suggested by HosipLan or eval the string. Evaluating seems a bit easier.

HosipLan
Moderator | 4668
+
0
-

I highly suggest you to use templates, you don't even have to save its output to file with ->save(), you can just cast it to string, it will output the result.

Don't use eval, its evil.

richard
Member | 60
+
0
-

I got it now. I use the template, cast to a string and get what I need.
I should have rather asked on how to use macros outside .latte templates.
Thanks to both.

HosipLan
Moderator | 4668
+
0
-

If you don't want to use files, there is always ->setSource() in Nette\Templating\Template, which works as StringTemplate.

richard
Member | 60
+
0
-

I have another question, please. How to get the macro content?

<?php
{macro argument}content{/macro}
$macroSet->addMacro('macro','echo "argument: ".%node.args.", content: ".$donotknow','');
?>

Last edited by richard (2011-08-31 21:35)

HosipLan
Moderator | 4668
+
0
-
use Nette\Latte;
use Nette\Latte\MacroNode;

class UIMacros extends Latte\Macros\MacroSet
{
	/**
	 * @param Latte\Parser $parser
	 */
	public static function install(Latte\Parser $parser)
	{
		$me = new static($parser);
		$me->addMacro('box', callback($me, 'macroBoxBegin'), "?><div><?php");
	}

	/**
	 * @param MacroNode $node
	 * @param Latte\PhpWriter $writer
	 */
	public function macroBoxBegin(MacroNode $node, $writer)
	{
		$node;
		$writer;

		return $writer->write('?><div><?php');
	}
}

In your method, you get a $node and $writer. $writer allows you to write your code to template. And $node contains information about your node in HTML & Latte tree.

Have a look at Nette\Latte\MacroNode & Nette\Latte\PhpWriter

richard
Member | 60
+
0
-

Hello HosipLan,

I am still unable to get content of macro:

<?php

	$template = new Nette\Templating\Template;
	$template->setSource("macro with {box}content in div{/box}");
	...............

	public function macroBoxBegin(MacroNode $node, $writer)
        {
                $node;
                $writer;
		Nette\Diagnostics\Debugger::dump($node->content);
                return $writer->write('?></div><?php');
        }
?>

It prints what supposed dumps null in $node->content.

Sorry for being pain in …

Thanks.

HosipLan
Moderator | 4668
+
0
-

I would suggest you to dump whole Node and try finding out it's descendants, if any.

richard
Member | 60
+
0
-

Sorry, I am not getting it…

This is my aim:
Users will enter text with defined macros in textarea.
It will create a page and submitting it will will log something via email or web services…

Therefore the syntax must be that simple.

Ie. their input:
Blah blah, this will be submitted to
{emailTo}franta,pepa,milan,{myself},{myboss}{/emailTo}

HTML Output:
Blah blah, this will be submitted to
<table>
<tr><td>frantisek.dobrota@fbi.gov</td><td>agent</tr>
<tr><td>pepa.novak@cia.gov</td><td>president</tr>

</table>
<submit>

Plus the action itself.

I am still not able to get content of macro parsed recursively.
Can I do it with Nette macros or is it overkill?

This is what I get with damping the node object:

<?php
Nette\Latte\MacroNode(11) {
   macro => UIMacros(2) {
      parser => Nette\Latte\Parser(10) {
         macroRe private => "
			(?P<comment>\{(?![\s'"{}])\*.*?\*\}\n{0,2})|
			\{(?![\s'"{}])
				(?P<macro>(?:'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"|[^'"]+?)*?)
			\}
			(?P< ... " (176)
         input private => "macro with {box}content in div{/box}" (36)
         output private => "macro with " (11)
         offset private => 16
         macros private => array(49) { ... }
         macroHandlers private => SplObjectStorage(0)
         htmlNodes private => array(0)
         macroNodes private => array(0)
         context => array(1) [ ... ]
         templateId => "vetmgixfr7" (10)
      }
      macros private => array(1) {
         box => array(2) [ ... ]
      }
   }
   name => "box" (3)
   isEmpty => FALSE
   args => ""
   modifiers => ""
   closing => FALSE
   tokenizer => Nette\Latte\MacroTokenizer(7) {
      tokens => array(0)
      position => 0
      ignored => array(2) [
         0 => 2
         1 => 1
      ]
      input private => ""
      re private => "~(\s+)|((?s)/\*.*?\*/)|('(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*")|((?:true|false|null|and|or|xor|clone|new|instanceof|return|continue|break|[A-Z_][A-Z0-9_] ... " (278)
      types private => array(9) [
         0 => 1
         1 => 2
         2 => 6
         3 => 8
         4 => 7
         5 => 5
         6 => 4
         7 => 3
         8 => 9
      ]
      current => NULL
   }
   offset => NULL
   parentNode => NULL
   content => NULL
   data => stdClass(0)
}

macro with
content in div



    504.1 ms
    6.87 MB
    Devel:default
    ×

?>

Last edited by richard (2011-09-01 18:08)

HosipLan
Moderator | 4668
+
0
-

I have thought, that this should be possible. At leas with $writter, it should allow you to manipulate with macro content.

Your concrete example that you have shown would be quite complicated to achieve with Latte. I'd rather create specific form for this task, if that's not a problem.