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: