1: <?php
2: /**
3: * Smarty Internal Plugin Data
4: * This file contains the basic classes and methods for template and variable creation
5: *
6: * @package Smarty
7: * @subpackage Template
8: * @author Uwe Tews
9: */
10:
11: /**
12: * Base class with template and variable methods
13: *
14: * @package Smarty
15: * @subpackage Template
16: */
17: class Smarty_Internal_Data
18: {
19: /**
20: * name of class used for templates
21: *
22: * @var string
23: */
24: public $template_class = 'Smarty_Internal_Template';
25: /**
26: * template variables
27: *
28: * @var array
29: */
30: public $tpl_vars = array();
31: /**
32: * parent template (if any)
33: *
34: * @var Smarty_Internal_Template
35: */
36: public $parent = null;
37: /**
38: * configuration settings
39: *
40: * @var array
41: */
42: public $config_vars = array();
43:
44: /**
45: * assigns a Smarty variable
46: *
47: * @param array|string $tpl_var the template variable name(s)
48: * @param mixed $value the value to assign
49: * @param boolean $nocache if true any output of this variable will be not cached
50: *
51: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
52: */
53: public function assign($tpl_var, $value = null, $nocache = false)
54: {
55: if (is_array($tpl_var)) {
56: foreach ($tpl_var as $_key => $_val) {
57: if ($_key != '') {
58: $this->tpl_vars[$_key] = new Smarty_variable($_val, $nocache);
59: }
60: }
61: } else {
62: if ($tpl_var != '') {
63: $this->tpl_vars[$tpl_var] = new Smarty_variable($value, $nocache);
64: }
65: }
66:
67: return $this;
68: }
69:
70: /**
71: * assigns a global Smarty variable
72: *
73: * @param string $varname the global variable name
74: * @param mixed $value the value to assign
75: * @param boolean $nocache if true any output of this variable will be not cached
76: *
77: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
78: */
79: public function assignGlobal($varname, $value = null, $nocache = false)
80: {
81: if ($varname != '') {
82: Smarty::$global_tpl_vars[$varname] = new Smarty_variable($value, $nocache);
83: $ptr = $this;
84: while ($ptr instanceof Smarty_Internal_Template) {
85: $ptr->tpl_vars[$varname] = clone Smarty::$global_tpl_vars[$varname];
86: $ptr = $ptr->parent;
87: }
88: }
89:
90: return $this;
91: }
92:
93: /**
94: * assigns values to template variables by reference
95: *
96: * @param string $tpl_var the template variable name
97: * @param $value
98: * @param boolean $nocache if true any output of this variable will be not cached
99: *
100: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
101: */
102: public function assignByRef($tpl_var, &$value, $nocache = false)
103: {
104: if ($tpl_var != '') {
105: $this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache);
106: $this->tpl_vars[$tpl_var]->value = & $value;
107: }
108:
109: return $this;
110: }
111:
112: /**
113: * appends values to template variables
114: *
115: * @param array|string $tpl_var the template variable name(s)
116: * @param mixed $value the value to append
117: * @param boolean $merge flag if array elements shall be merged
118: * @param boolean $nocache if true any output of this variable will be not cached
119: *
120: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
121: */
122: public function append($tpl_var, $value = null, $merge = false, $nocache = false)
123: {
124: if (is_array($tpl_var)) {
125: // $tpl_var is an array, ignore $value
126: foreach ($tpl_var as $_key => $_val) {
127: if ($_key != '') {
128: if (!isset($this->tpl_vars[$_key])) {
129: $tpl_var_inst = $this->getVariable($_key, null, true, false);
130: if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
131: $this->tpl_vars[$_key] = new Smarty_variable(null, $nocache);
132: } else {
133: $this->tpl_vars[$_key] = clone $tpl_var_inst;
134: }
135: }
136: if (!(is_array($this->tpl_vars[$_key]->value) || $this->tpl_vars[$_key]->value instanceof ArrayAccess)) {
137: settype($this->tpl_vars[$_key]->value, 'array');
138: }
139: if ($merge && is_array($_val)) {
140: foreach ($_val as $_mkey => $_mval) {
141: $this->tpl_vars[$_key]->value[$_mkey] = $_mval;
142: }
143: } else {
144: $this->tpl_vars[$_key]->value[] = $_val;
145: }
146: }
147: }
148: } else {
149: if ($tpl_var != '' && isset($value)) {
150: if (!isset($this->tpl_vars[$tpl_var])) {
151: $tpl_var_inst = $this->getVariable($tpl_var, null, true, false);
152: if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
153: $this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache);
154: } else {
155: $this->tpl_vars[$tpl_var] = clone $tpl_var_inst;
156: }
157: }
158: if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) {
159: settype($this->tpl_vars[$tpl_var]->value, 'array');
160: }
161: if ($merge && is_array($value)) {
162: foreach ($value as $_mkey => $_mval) {
163: $this->tpl_vars[$tpl_var]->value[$_mkey] = $_mval;
164: }
165: } else {
166: $this->tpl_vars[$tpl_var]->value[] = $value;
167: }
168: }
169: }
170:
171: return $this;
172: }
173:
174: /**
175: * appends values to template variables by reference
176: *
177: * @param string $tpl_var the template variable name
178: * @param mixed &$value the referenced value to append
179: * @param boolean $merge flag if array elements shall be merged
180: *
181: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
182: */
183: public function appendByRef($tpl_var, &$value, $merge = false)
184: {
185: if ($tpl_var != '' && isset($value)) {
186: if (!isset($this->tpl_vars[$tpl_var])) {
187: $this->tpl_vars[$tpl_var] = new Smarty_variable();
188: }
189: if (!is_array($this->tpl_vars[$tpl_var]->value)) {
190: settype($this->tpl_vars[$tpl_var]->value, 'array');
191: }
192: if ($merge && is_array($value)) {
193: foreach ($value as $_key => $_val) {
194: $this->tpl_vars[$tpl_var]->value[$_key] = & $value[$_key];
195: }
196: } else {
197: $this->tpl_vars[$tpl_var]->value[] = & $value;
198: }
199: }
200:
201: return $this;
202: }
203:
204: /**
205: * Returns a single or all template variables
206: *
207: * @param string $varname variable name or null
208: * @param object $_ptr optional pointer to data object
209: * @param boolean $search_parents include parent templates?
210: *
211: * @return string variable value or or array of variables
212: */
213: public function getTemplateVars($varname = null, $_ptr = null, $search_parents = true)
214: {
215: if (isset($varname)) {
216: $_var = $this->getVariable($varname, $_ptr, $search_parents, false);
217: if (is_object($_var)) {
218: return $_var->value;
219: } else {
220: return null;
221: }
222: } else {
223: $_result = array();
224: if ($_ptr === null) {
225: $_ptr = $this;
226: }
227: while ($_ptr !== null) {
228: foreach ($_ptr->tpl_vars AS $key => $var) {
229: if (!array_key_exists($key, $_result)) {
230: $_result[$key] = $var->value;
231: }
232: }
233: // not found, try at parent
234: if ($search_parents) {
235: $_ptr = $_ptr->parent;
236: } else {
237: $_ptr = null;
238: }
239: }
240: if ($search_parents && isset(Smarty::$global_tpl_vars)) {
241: foreach (Smarty::$global_tpl_vars AS $key => $var) {
242: if (!array_key_exists($key, $_result)) {
243: $_result[$key] = $var->value;
244: }
245: }
246: }
247:
248: return $_result;
249: }
250: }
251:
252: /**
253: * clear the given assigned template variable.
254: *
255: * @param string|array $tpl_var the template variable(s) to clear
256: *
257: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
258: */
259: public function clearAssign($tpl_var)
260: {
261: if (is_array($tpl_var)) {
262: foreach ($tpl_var as $curr_var) {
263: unset($this->tpl_vars[$curr_var]);
264: }
265: } else {
266: unset($this->tpl_vars[$tpl_var]);
267: }
268:
269: return $this;
270: }
271:
272: /**
273: * clear all the assigned template variables.
274: *
275: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
276: */
277: public function clearAllAssign()
278: {
279: $this->tpl_vars = array();
280:
281: return $this;
282: }
283:
284: /**
285: * load a config file, optionally load just selected sections
286: *
287: * @param string $config_file filename
288: * @param mixed $sections array of section names, single section or null
289: *
290: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
291: */
292: public function configLoad($config_file, $sections = null)
293: {
294: // load Config class
295: $config = new Smarty_Internal_Config($config_file, $this->smarty, $this);
296: $config->loadConfigVars($sections);
297:
298: return $this;
299: }
300:
301: /**
302: * gets the object of a Smarty variable
303: *
304: * @param string $variable the name of the Smarty variable
305: * @param object $_ptr optional pointer to data object
306: * @param boolean $search_parents search also in parent data
307: * @param bool $error_enable
308: *
309: * @return object the object of the variable
310: */
311: public function getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true)
312: {
313: if ($_ptr === null) {
314: $_ptr = $this;
315: }
316: while ($_ptr !== null) {
317: if (isset($_ptr->tpl_vars[$variable])) {
318: // found it, return it
319: return $_ptr->tpl_vars[$variable];
320: }
321: // not found, try at parent
322: if ($search_parents) {
323: $_ptr = $_ptr->parent;
324: } else {
325: $_ptr = null;
326: }
327: }
328: if (isset(Smarty::$global_tpl_vars[$variable])) {
329: // found it, return it
330: return Smarty::$global_tpl_vars[$variable];
331: }
332: if ($this->smarty->error_unassigned && $error_enable) {
333: // force a notice
334: $x = $$variable;
335: }
336:
337: return new Undefined_Smarty_Variable;
338: }
339:
340: /**
341: * gets a config variable
342: *
343: * @param string $variable the name of the config variable
344: * @param bool $error_enable
345: *
346: * @return mixed the value of the config variable
347: */
348: public function getConfigVariable($variable, $error_enable = true)
349: {
350: $_ptr = $this;
351: while ($_ptr !== null) {
352: if (isset($_ptr->config_vars[$variable])) {
353: // found it, return it
354: return $_ptr->config_vars[$variable];
355: }
356: // not found, try at parent
357: $_ptr = $_ptr->parent;
358: }
359: if ($this->smarty->error_unassigned && $error_enable) {
360: // force a notice
361: $x = $$variable;
362: }
363:
364: return null;
365: }
366:
367: /**
368: * gets a stream variable
369: *
370: * @param string $variable the stream of the variable
371: *
372: * @throws SmartyException
373: * @return mixed the value of the stream variable
374: */
375: public function getStreamVariable($variable)
376: {
377: $_result = '';
378: $fp = fopen($variable, 'r+');
379: if ($fp) {
380: while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
381: $_result .= $current_line;
382: }
383: fclose($fp);
384:
385: return $_result;
386: }
387:
388: if ($this->smarty->error_unassigned) {
389: throw new SmartyException('Undefined stream variable "' . $variable . '"');
390: } else {
391: return null;
392: }
393: }
394:
395: /**
396: * Returns a single or all config variables
397: *
398: * @param string $varname variable name or null
399: * @param bool $search_parents
400: *
401: * @return string variable value or or array of variables
402: */
403: public function getConfigVars($varname = null, $search_parents = true)
404: {
405: $_ptr = $this;
406: $var_array = array();
407: while ($_ptr !== null) {
408: if (isset($varname)) {
409: if (isset($_ptr->config_vars[$varname])) {
410: return $_ptr->config_vars[$varname];
411: }
412: } else {
413: $var_array = array_merge($_ptr->config_vars, $var_array);
414: }
415: // not found, try at parent
416: if ($search_parents) {
417: $_ptr = $_ptr->parent;
418: } else {
419: $_ptr = null;
420: }
421: }
422: if (isset($varname)) {
423: return '';
424: } else {
425: return $var_array;
426: }
427: }
428:
429: /**
430: * Deassigns a single or all config variables
431: *
432: * @param string $varname variable name or null
433: *
434: * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
435: */
436: public function clearConfig($varname = null)
437: {
438: if (isset($varname)) {
439: unset($this->config_vars[$varname]);
440: } else {
441: $this->config_vars = array();
442: }
443:
444: return $this;
445: }
446: }
447:
448: /**
449: * class for the Smarty data object
450: * The Smarty data object will hold Smarty variables in the current scope
451: *
452: * @package Smarty
453: * @subpackage Template
454: */
455: class Smarty_Data extends Smarty_Internal_Data
456: {
457: /**
458: * Smarty object
459: *
460: * @var Smarty
461: */
462: public $smarty = null;
463:
464: /**
465: * create Smarty data object
466: *
467: * @param Smarty|array $_parent parent template
468: * @param Smarty|Smarty_Internal_Template $smarty global smarty instance
469: *
470: * @throws SmartyException
471: */
472: public function __construct($_parent = null, $smarty = null)
473: {
474: $this->smarty = $smarty;
475: if (is_object($_parent)) {
476: // when object set up back pointer
477: $this->parent = $_parent;
478: } elseif (is_array($_parent)) {
479: // set up variable values
480: foreach ($_parent as $_key => $_val) {
481: $this->tpl_vars[$_key] = new Smarty_variable($_val);
482: }
483: } elseif ($_parent != null) {
484: throw new SmartyException("Wrong type for template variables");
485: }
486: }
487: }
488:
489: /**
490: * class for the Smarty variable object
491: * This class defines the Smarty variable object
492: *
493: * @package Smarty
494: * @subpackage Template
495: */
496: class Smarty_Variable
497: {
498: /**
499: * template variable
500: *
501: * @var mixed
502: */
503: public $value = null;
504: /**
505: * if true any output of this variable will be not cached
506: *
507: * @var boolean
508: */
509: public $nocache = false;
510: /**
511: * the scope the variable will have (local,parent or root)
512: *
513: * @var int
514: */
515: public $scope = Smarty::SCOPE_LOCAL;
516:
517: /**
518: * create Smarty variable object
519: *
520: * @param mixed $value the value to assign
521: * @param boolean $nocache if true any output of this variable will be not cached
522: * @param int $scope the scope the variable will have (local,parent or root)
523: */
524: public function __construct($value = null, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
525: {
526: $this->value = $value;
527: $this->nocache = $nocache;
528: $this->scope = $scope;
529: }
530:
531: /**
532: * <<magic>> String conversion
533: *
534: * @return string
535: */
536: public function __toString()
537: {
538: return (string) $this->value;
539: }
540: }
541:
542: /**
543: * class for undefined variable object
544: * This class defines an object for undefined variable handling
545: *
546: * @package Smarty
547: * @subpackage Template
548: */
549: class Undefined_Smarty_Variable
550: {
551: /**
552: * Returns FALSE for 'nocache' and NULL otherwise.
553: *
554: * @param string $name
555: *
556: * @return bool
557: */
558: public function __get($name)
559: {
560: if ($name == 'nocache') {
561: return false;
562: } else {
563: return null;
564: }
565: }
566:
567: /**
568: * Always returns an empty string.
569: *
570: * @return string
571: */
572: public function __toString()
573: {
574: return "";
575: }
576: }
577: