1: <?php
2:
3: /**
4: * Runtime Extension Capture
5: *
6: * @package Smarty
7: * @subpackage PluginsInternal
8: * @author Uwe Tews
9: */
10: class Smarty_Internal_Runtime_Capture
11: {
12: /**
13: * Flag that this instance will not be cached
14: *
15: * @var bool
16: */
17: public $isPrivateExtension = true;
18:
19: /**
20: * Stack of capture parameter
21: *
22: * @var array
23: */
24: private $captureStack = array();
25:
26: /**
27: * Current open capture sections
28: *
29: * @var int
30: */
31: private $captureCount = 0;
32:
33: /**
34: * Count stack
35: *
36: * @var int[]
37: */
38: private $countStack = array();
39:
40: /**
41: * Named buffer
42: *
43: * @var string[]
44: */
45: private $namedBuffer = array();
46:
47: /**
48: * Flag if callbacks are registered
49: *
50: * @var bool
51: */
52: private $isRegistered = false;
53:
54: /**
55: * Open capture section
56: *
57: * @param \Smarty_Internal_Template $_template
58: * @param string $buffer capture name
59: * @param string $assign variable name
60: * @param string $append variable name
61: */
62: public function open(Smarty_Internal_Template $_template, $buffer, $assign, $append)
63: {
64: if (!$this->isRegistered) {
65: $this->register($_template);
66: }
67: $this->captureStack[] = array(
68: $buffer,
69: $assign,
70: $append
71: );
72: $this->captureCount++;
73: ob_start();
74: }
75:
76: /**
77: * Register callbacks in template class
78: *
79: * @param \Smarty_Internal_Template $_template
80: */
81: private function register(Smarty_Internal_Template $_template)
82: {
83: $_template->startRenderCallbacks[] = array(
84: $this,
85: 'startRender'
86: );
87: $_template->endRenderCallbacks[] = array(
88: $this,
89: 'endRender'
90: );
91: $this->startRender($_template);
92: $this->isRegistered = true;
93: }
94:
95: /**
96: * Start render callback
97: *
98: * @param \Smarty_Internal_Template $_template
99: */
100: public function startRender(Smarty_Internal_Template $_template)
101: {
102: $this->countStack[] = $this->captureCount;
103: $this->captureCount = 0;
104: }
105:
106: /**
107: * Close capture section
108: *
109: * @param \Smarty_Internal_Template $_template
110: *
111: * @throws \SmartyException
112: */
113: public function close(Smarty_Internal_Template $_template)
114: {
115: if ($this->captureCount) {
116: list($buffer, $assign, $append) = array_pop($this->captureStack);
117: $this->captureCount--;
118: if (isset($assign)) {
119: $_template->assign($assign, ob_get_contents());
120: }
121: if (isset($append)) {
122: $_template->append($append, ob_get_contents());
123: }
124: $this->namedBuffer[ $buffer ] = ob_get_clean();
125: } else {
126: $this->error($_template);
127: }
128: }
129:
130: /**
131: * Error exception on not matching {capture}{/capture}
132: *
133: * @param \Smarty_Internal_Template $_template
134: *
135: * @throws \SmartyException
136: */
137: public function error(Smarty_Internal_Template $_template)
138: {
139: throw new SmartyException("Not matching {capture}{/capture} in '{$_template->template_resource}'");
140: }
141:
142: /**
143: * Return content of named capture buffer by key or as array
144: *
145: * @param \Smarty_Internal_Template $_template
146: * @param string|null $name
147: *
148: * @return string|string[]|null
149: */
150: public function getBuffer(Smarty_Internal_Template $_template, $name = null)
151: {
152: if (isset($name)) {
153: return isset($this->namedBuffer[ $name ]) ? $this->namedBuffer[ $name ] : null;
154: } else {
155: return $this->namedBuffer;
156: }
157: }
158:
159: /**
160: * End render callback
161: *
162: * @param \Smarty_Internal_Template $_template
163: *
164: * @throws \SmartyException
165: */
166: public function endRender(Smarty_Internal_Template $_template)
167: {
168: if ($this->captureCount) {
169: $this->error($_template);
170: } else {
171: $this->captureCount = array_pop($this->countStack);
172: }
173: }
174: }
175: