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