1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Latte\Macros;
9:
10: use Latte;
11: use Latte\MacroNode;
12:
13:
14: 15: 16:
17: class MacroSet extends Latte\Object implements Latte\IMacro
18: {
19:
20: private $compiler;
21:
22:
23: private $macros;
24:
25:
26: public function __construct(Latte\Compiler $compiler)
27: {
28: $this->compiler = $compiler;
29: }
30:
31:
32: public function addMacro($name, $begin, $end = NULL, $attr = NULL)
33: {
34: if (!$begin && !$end && !$attr) {
35: throw new \InvalidArgumentException("At least one argument must be specified for macro '$name'.");
36: }
37: foreach (array($begin, $end, $attr) as $arg) {
38: if ($arg && !is_string($arg)) {
39: Latte\Helpers::checkCallback($arg);
40: }
41: }
42:
43: $this->macros[$name] = array($begin, $end, $attr);
44: $this->compiler->addMacro($name, $this);
45: return $this;
46: }
47:
48:
49: 50: 51: 52:
53: public function initialize()
54: {
55: }
56:
57:
58: 59: 60: 61:
62: public function finalize()
63: {
64: }
65:
66:
67: 68: 69: 70:
71: public function nodeOpened(MacroNode $node)
72: {
73: list($begin, $end, $attr) = $this->macros[$node->name];
74: $node->isEmpty = !$end;
75:
76: if ($attr && $node->prefix === $node::PREFIX_NONE) {
77: $node->isEmpty = TRUE;
78: $this->compiler->setContext(Latte\Compiler::CONTEXT_DOUBLE_QUOTED_ATTR);
79: $res = $this->compile($node, $attr);
80: if ($res === FALSE) {
81: return FALSE;
82: } elseif (!$node->attrCode) {
83: $node->attrCode = "<?php $res ?>";
84: }
85: $this->compiler->setContext(NULL);
86:
87: } elseif ($begin) {
88: $res = $this->compile($node, $begin);
89: if ($res === FALSE || ($node->isEmpty && $node->prefix)) {
90: return FALSE;
91: } elseif (!$node->openingCode) {
92: $node->openingCode = "<?php $res ?>";
93: }
94:
95: } elseif (!$end) {
96: return FALSE;
97: }
98: }
99:
100:
101: 102: 103: 104:
105: public function nodeClosed(MacroNode $node)
106: {
107: if (isset($this->macros[$node->name][1])) {
108: $res = $this->compile($node, $this->macros[$node->name][1]);
109: if (!$node->closingCode) {
110: $node->closingCode = "<?php $res ?>";
111: }
112: }
113: }
114:
115:
116: 117: 118: 119:
120: private function compile(MacroNode $node, $def)
121: {
122: $node->tokenizer->reset();
123: $writer = Latte\PhpWriter::using($node, $this->compiler);
124: if (is_string($def)) {
125: return $writer->write($def);
126: } else {
127: return call_user_func($def, $node, $writer);
128: }
129: }
130:
131:
132: 133: 134:
135: public function getCompiler()
136: {
137: return $this->compiler;
138: }
139:
140: }
141: