1: <?php
2:
3: /**
4: * Smarty Extension handler
5: *
6: * Load extensions dynamically
7: *
8: * @package Smarty
9: * @subpackage PluginsInternal
10: * @author Uwe Tews
11: *
12: * Runtime extensions
13: * @property Smarty_Internal_Runtime_CacheModify $_cacheModify
14: * @property Smarty_Internal_Runtime_CacheResourceFile $_cacheResourceFile
15: * @property Smarty_Internal_Runtime_Capture $_capture
16: * @property Smarty_Internal_Runtime_CodeFrame $_codeFrame
17: * @property Smarty_Internal_Runtime_FilterHandler $_filterHandler
18: * @property Smarty_Internal_Runtime_Foreach $_foreach
19: * @property Smarty_Internal_Runtime_GetIncludePath $_getIncludePath
20: * @property Smarty_Internal_Runtime_Make_Nocache $_make_nocache
21: * @property Smarty_Internal_Runtime_UpdateCache $_updateCache
22: * @property Smarty_Internal_Runtime_UpdateScope $_updateScope
23: * @property Smarty_Internal_Runtime_TplFunction $_tplFunction
24: * @property Smarty_Internal_Runtime_WriteFile $_writeFile
25: *
26: * Method extensions
27: * @property Smarty_Internal_Method_GetTemplateVars $getTemplateVars
28: * @property Smarty_Internal_Method_Append $append
29: * @property Smarty_Internal_Method_AppendByRef $appendByRef
30: * @property Smarty_Internal_Method_AssignGlobal $assignGlobal
31: * @property Smarty_Internal_Method_AssignByRef $assignByRef
32: * @property Smarty_Internal_Method_LoadFilter $loadFilter
33: * @property Smarty_Internal_Method_LoadPlugin $loadPlugin
34: * @property Smarty_Internal_Method_RegisterFilter $registerFilter
35: * @property Smarty_Internal_Method_RegisterObject $registerObject
36: * @property Smarty_Internal_Method_RegisterPlugin $registerPlugin
37: * @property mixed|\Smarty_Template_Cached configLoad
38: */
39: class Smarty_Internal_Extension_Handler
40: {
41: public $objType = null;
42:
43: /**
44: * Cache for property information from generic getter/setter
45: * Preloaded with names which should not use with generic getter/setter
46: *
47: * @var array
48: */
49: private $_property_info = array(
50: 'AutoloadFilters' => 0, 'DefaultModifiers' => 0, 'ConfigVars' => 0,
51: 'DebugTemplate' => 0, 'RegisteredObject' => 0, 'StreamVariable' => 0,
52: 'TemplateVars' => 0, 'Literals' => 'Literals',
53: );//
54:
55: private $resolvedProperties = array();
56:
57: /**
58: * Call external Method
59: *
60: * @param \Smarty_Internal_Data $data
61: * @param string $name external method names
62: * @param array $args argument array
63: *
64: * @return mixed
65: */
66: public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args)
67: {
68: /* @var Smarty $data ->smarty */
69: $smarty = isset($data->smarty) ? $data->smarty : $data;
70: if (!isset($smarty->ext->$name)) {
71: if (preg_match('/^((set|get)|(.*?))([A-Z].*)$/', $name, $match)) {
72: $basename = $this->upperCase($match[ 4 ]);
73: if (!isset($smarty->ext->$basename) && isset($this->_property_info[ $basename ])
74: && is_string($this->_property_info[ $basename ])
75: ) {
76: $class = 'Smarty_Internal_Method_' . $this->_property_info[ $basename ];
77: if (class_exists($class)) {
78: $classObj = new $class();
79: $methodes = get_class_methods($classObj);
80: foreach ($methodes as $method) {
81: $smarty->ext->$method = $classObj;
82: }
83: }
84: }
85: if (!empty($match[ 2 ]) && !isset($smarty->ext->$name)) {
86: $class = 'Smarty_Internal_Method_' . $this->upperCase($name);
87: if (!class_exists($class)) {
88: $objType = $data->_objType;
89: $propertyType = false;
90: if (!isset($this->resolvedProperties[ $match[ 0 ] ][ $objType ])) {
91: $property = isset($this->resolvedProperties[ 'property' ][ $basename ]) ?
92: $this->resolvedProperties[ 'property' ][ $basename ] :
93: $property = $this->resolvedProperties[ 'property' ][ $basename ] = strtolower(
94: join(
95: '_',
96: preg_split(
97: '/([A-Z][^A-Z]*)/',
98: $basename,
99: -1,
100: PREG_SPLIT_NO_EMPTY |
101: PREG_SPLIT_DELIM_CAPTURE
102: )
103: )
104: );
105: if ($property !== false) {
106: if (property_exists($data, $property)) {
107: $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ] = 1;
108: } elseif (property_exists($smarty, $property)) {
109: $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ] = 2;
110: } else {
111: $this->resolvedProperties[ 'property' ][ $basename ] = $property = false;
112: }
113: }
114: } else {
115: $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ];
116: $property = $this->resolvedProperties[ 'property' ][ $basename ];
117: }
118: if ($propertyType) {
119: $obj = $propertyType === 1 ? $data : $smarty;
120: if ($match[ 2 ] === 'get') {
121: return $obj->$property;
122: } elseif ($match[ 2 ] === 'set') {
123: return $obj->$property = $args[ 0 ];
124: }
125: }
126: }
127: }
128: }
129: }
130: $callback = array($smarty->ext->$name, $name);
131: array_unshift($args, $data);
132: if (isset($callback) && $callback[ 0 ]->objMap | $data->_objType) {
133: return call_user_func_array($callback, $args);
134: }
135: return call_user_func_array(array(new Smarty_Internal_Undefined(), $name), $args);
136: }
137:
138: /**
139: * Make first character of name parts upper case
140: *
141: * @param string $name
142: *
143: * @return string
144: */
145: public function upperCase($name)
146: {
147: $_name = explode('_', $name);
148: $_name = array_map('ucfirst', $_name);
149: return implode('_', $_name);
150: }
151:
152: /**
153: * get extension object
154: *
155: * @param string $property_name property name
156: *
157: * @return mixed|Smarty_Template_Cached
158: */
159: public function __get($property_name)
160: {
161: // object properties of runtime template extensions will start with '_'
162: if ($property_name[ 0 ] === '_') {
163: $class = 'Smarty_Internal_Runtime' . $this->upperCase($property_name);
164: } else {
165: $class = 'Smarty_Internal_Method_' . $this->upperCase($property_name);
166: }
167: if (!class_exists($class)) {
168: return $this->$property_name = new Smarty_Internal_Undefined($class);
169: }
170: return $this->$property_name = new $class();
171: }
172:
173: /**
174: * set extension property
175: *
176: * @param string $property_name property name
177: * @param mixed $value value
178: *
179: */
180: public function __set($property_name, $value)
181: {
182: $this->$property_name = $value;
183: }
184:
185: /**
186: * Call error handler for undefined method
187: *
188: * @param string $name unknown method-name
189: * @param array $args argument array
190: *
191: * @return mixed
192: */
193: public function __call($name, $args)
194: {
195: return call_user_func_array(array(new Smarty_Internal_Undefined(), $name), array($this));
196: }
197: }
198: