Commit | Line | Data |
---|---|---|
2aa91ff2 S |
1 | <?php |
2 | /** | |
3 | * Smarty Internal Plugin Smarty Template Base | |
4 | * This file contains the basic shared methods for template handling | |
5 | * | |
6 | * @package Smarty | |
7 | * @subpackage Template | |
8 | * @author Uwe Tews | |
9 | */ | |
10 | ||
11 | /** | |
12 | * Class with shared template methods | |
13 | * | |
14 | * @package Smarty | |
15 | * @subpackage Template | |
16 | */ | |
17 | abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data | |
18 | { | |
19 | /** | |
ccd27f54 S |
20 | * Set this if you want different sets of cache files for the same |
21 | * templates. | |
2aa91ff2 | 22 | * |
ccd27f54 S |
23 | * @var string |
24 | */ | |
25 | public $cache_id = null; | |
26 | /** | |
27 | * Set this if you want different sets of compiled files for the same | |
28 | * templates. | |
2aa91ff2 | 29 | * |
ccd27f54 | 30 | * @var string |
2aa91ff2 | 31 | */ |
ccd27f54 | 32 | public $compile_id = null; |
2aa91ff2 | 33 | /** |
ccd27f54 | 34 | * caching enabled |
2aa91ff2 | 35 | * |
ccd27f54 | 36 | * @var boolean |
2aa91ff2 | 37 | */ |
ccd27f54 S |
38 | public $caching = false; |
39 | /** | |
40 | * cache lifetime in seconds | |
41 | * | |
42 | * @var integer | |
43 | */ | |
44 | public $cache_lifetime = 3600; | |
2aa91ff2 S |
45 | |
46 | /** | |
47 | * test if cache is valid | |
48 | * | |
49 | * @param string|object $template the resource handle of the template file or template object | |
50 | * @param mixed $cache_id cache id to be used with this template | |
51 | * @param mixed $compile_id compile id to be used with this template | |
52 | * @param object $parent next higher level of Smarty variables | |
53 | * | |
54 | * @return boolean cache status | |
55 | */ | |
56 | public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) | |
57 | { | |
58 | if ($template === null && $this instanceof $this->template_class) { | |
ccd27f54 S |
59 | $template = $this; |
60 | } else { | |
61 | if (!($template instanceof $this->template_class)) { | |
62 | if ($parent === null) { | |
63 | $parent = $this; | |
64 | } | |
65 | $smarty = isset($this->smarty) ? $this->smarty : $this; | |
66 | $template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); | |
2aa91ff2 | 67 | } |
2aa91ff2 S |
68 | } |
69 | // return cache status of template | |
ccd27f54 S |
70 | if (!isset($template->cached)) { |
71 | $template->loadCached(); | |
72 | } | |
73 | return $template->cached->isCached($template); | |
2aa91ff2 S |
74 | } |
75 | ||
76 | /** | |
77 | * creates a data object | |
78 | * | |
79 | * @param object $parent next higher level of Smarty variables | |
ccd27f54 | 80 | * @param string $name optional data block name |
2aa91ff2 S |
81 | * |
82 | * @returns Smarty_Data data object | |
83 | */ | |
ccd27f54 S |
84 | public function createData($parent = null, $name = null) |
85 | { | |
86 | $dataObj = new Smarty_Data($parent, $this, $name); | |
87 | if ($this->debugging) { | |
88 | Smarty_Internal_Debug::register_data($dataObj); | |
89 | } | |
90 | return $dataObj; | |
91 | } | |
92 | ||
93 | /** | |
94 | * Get unique template id | |
95 | * | |
96 | * @param string $template_name | |
97 | * @param null|mixed $cache_id | |
98 | * @param null|mixed $compile_id | |
99 | * | |
100 | * @return string | |
101 | */ | |
102 | public function getTemplateId($template_name, $cache_id = null, $compile_id = null) | |
2aa91ff2 | 103 | { |
ccd27f54 S |
104 | $cache_id = isset($cache_id) ? $cache_id : $this->cache_id; |
105 | $compile_id = isset($compile_id) ? $compile_id : $this->compile_id; | |
106 | $smarty = isset($this->smarty) ? $this->smarty : $this; | |
107 | if ($smarty->allow_ambiguous_resources) { | |
108 | $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}"; | |
109 | } else { | |
110 | $_templateId = $smarty->joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}"; | |
111 | } | |
112 | if (isset($_templateId[150])) { | |
113 | $_templateId = sha1($_templateId); | |
114 | } | |
115 | return $_templateId; | |
2aa91ff2 S |
116 | } |
117 | ||
118 | /** | |
119 | * Registers plugin to be used in templates | |
120 | * | |
121 | * @param string $type plugin type | |
122 | * @param string $tag name of template tag | |
123 | * @param callback $callback PHP callback to register | |
124 | * @param boolean $cacheable if true (default) this fuction is cachable | |
125 | * @param array $cache_attr caching attributes if any | |
126 | * | |
ccd27f54 S |
127 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
128 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
129 | * @throws SmartyException when the plugin tag is invalid |
130 | */ | |
131 | public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null) | |
132 | { | |
ccd27f54 S |
133 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
134 | if (isset($smarty->registered_plugins[$type][$tag])) { | |
2aa91ff2 S |
135 | throw new SmartyException("Plugin tag \"{$tag}\" already registered"); |
136 | } elseif (!is_callable($callback)) { | |
137 | throw new SmartyException("Plugin \"{$tag}\" not callable"); | |
138 | } else { | |
ccd27f54 | 139 | $smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr); |
2aa91ff2 S |
140 | } |
141 | ||
142 | return $this; | |
143 | } | |
144 | ||
145 | /** | |
146 | * Unregister Plugin | |
147 | * | |
148 | * @param string $type of plugin | |
149 | * @param string $tag name of plugin | |
150 | * | |
ccd27f54 S |
151 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
152 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
153 | */ |
154 | public function unregisterPlugin($type, $tag) | |
155 | { | |
ccd27f54 S |
156 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
157 | if (isset($smarty->registered_plugins[$type][$tag])) { | |
158 | unset($smarty->registered_plugins[$type][$tag]); | |
2aa91ff2 S |
159 | } |
160 | ||
161 | return $this; | |
162 | } | |
163 | ||
164 | /** | |
165 | * Registers a resource to fetch a template | |
166 | * | |
167 | * @param string $type name of resource type | |
ccd27f54 S |
168 | * @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource |
169 | * (deprecated) | |
2aa91ff2 | 170 | * |
ccd27f54 S |
171 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
172 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
173 | */ |
174 | public function registerResource($type, $callback) | |
175 | { | |
ccd27f54 S |
176 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
177 | $smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false); | |
2aa91ff2 S |
178 | |
179 | return $this; | |
180 | } | |
181 | ||
182 | /** | |
183 | * Unregisters a resource | |
184 | * | |
185 | * @param string $type name of resource type | |
186 | * | |
ccd27f54 S |
187 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
188 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
189 | */ |
190 | public function unregisterResource($type) | |
191 | { | |
ccd27f54 S |
192 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
193 | if (isset($smarty->registered_resources[$type])) { | |
194 | unset($smarty->registered_resources[$type]); | |
2aa91ff2 S |
195 | } |
196 | ||
197 | return $this; | |
198 | } | |
199 | ||
200 | /** | |
201 | * Registers a cache resource to cache a template's output | |
202 | * | |
203 | * @param string $type name of cache resource type | |
204 | * @param Smarty_CacheResource $callback instance of Smarty_CacheResource to handle output caching | |
205 | * | |
ccd27f54 S |
206 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
207 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
208 | */ |
209 | public function registerCacheResource($type, Smarty_CacheResource $callback) | |
210 | { | |
ccd27f54 S |
211 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
212 | $smarty->registered_cache_resources[$type] = $callback; | |
2aa91ff2 S |
213 | |
214 | return $this; | |
215 | } | |
216 | ||
217 | /** | |
218 | * Unregisters a cache resource | |
219 | * | |
220 | * @param string $type name of cache resource type | |
221 | * | |
ccd27f54 S |
222 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
223 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
224 | */ |
225 | public function unregisterCacheResource($type) | |
226 | { | |
ccd27f54 S |
227 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
228 | if (isset($smarty->registered_cache_resources[$type])) { | |
229 | unset($smarty->registered_cache_resources[$type]); | |
2aa91ff2 S |
230 | } |
231 | ||
232 | return $this; | |
233 | } | |
234 | ||
235 | /** | |
236 | * Registers object to be used in templates | |
237 | * | |
238 | * @param $object_name | |
239 | * @param object $object_impl the referenced PHP object to register | |
240 | * @param array $allowed list of allowed methods (empty = all) | |
241 | * @param boolean $smarty_args smarty argument format, else traditional | |
242 | * @param array $block_methods list of block-methods | |
243 | * | |
244 | * @throws SmartyException | |
ccd27f54 S |
245 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
246 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
247 | */ |
248 | public function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) | |
249 | { | |
250 | // test if allowed methods callable | |
251 | if (!empty($allowed)) { | |
252 | foreach ((array) $allowed as $method) { | |
253 | if (!is_callable(array($object_impl, $method)) && !property_exists($object_impl, $method)) { | |
254 | throw new SmartyException("Undefined method or property '$method' in registered object"); | |
255 | } | |
256 | } | |
257 | } | |
258 | // test if block methods callable | |
259 | if (!empty($block_methods)) { | |
260 | foreach ((array) $block_methods as $method) { | |
261 | if (!is_callable(array($object_impl, $method))) { | |
262 | throw new SmartyException("Undefined method '$method' in registered object"); | |
263 | } | |
264 | } | |
265 | } | |
266 | // register the object | |
ccd27f54 S |
267 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
268 | $smarty->registered_objects[$object_name] = | |
2aa91ff2 S |
269 | array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods); |
270 | ||
271 | return $this; | |
272 | } | |
273 | ||
274 | /** | |
275 | * return a reference to a registered object | |
276 | * | |
277 | * @param string $name object name | |
278 | * | |
279 | * @return object | |
280 | * @throws SmartyException if no such object is found | |
281 | */ | |
282 | public function getRegisteredObject($name) | |
283 | { | |
ccd27f54 S |
284 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
285 | if (!isset($smarty->registered_objects[$name])) { | |
2aa91ff2 S |
286 | throw new SmartyException("'$name' is not a registered object"); |
287 | } | |
ccd27f54 | 288 | if (!is_object($smarty->registered_objects[$name][0])) { |
2aa91ff2 S |
289 | throw new SmartyException("registered '$name' is not an object"); |
290 | } | |
291 | ||
ccd27f54 | 292 | return $smarty->registered_objects[$name][0]; |
2aa91ff2 S |
293 | } |
294 | ||
295 | /** | |
296 | * unregister an object | |
297 | * | |
298 | * @param string $name object name | |
299 | * | |
ccd27f54 S |
300 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
301 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
302 | */ |
303 | public function unregisterObject($name) | |
304 | { | |
ccd27f54 S |
305 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
306 | if (isset($smarty->registered_objects[$name])) { | |
307 | unset($smarty->registered_objects[$name]); | |
2aa91ff2 S |
308 | } |
309 | ||
310 | return $this; | |
311 | } | |
312 | ||
313 | /** | |
314 | * Registers static classes to be used in templates | |
315 | * | |
316 | * @param $class_name | |
317 | * @param string $class_impl the referenced PHP class to register | |
318 | * | |
319 | * @throws SmartyException | |
ccd27f54 S |
320 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
321 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
322 | */ |
323 | public function registerClass($class_name, $class_impl) | |
324 | { | |
325 | // test if exists | |
326 | if (!class_exists($class_impl)) { | |
327 | throw new SmartyException("Undefined class '$class_impl' in register template class"); | |
328 | } | |
329 | // register the class | |
ccd27f54 S |
330 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
331 | $smarty->registered_classes[$class_name] = $class_impl; | |
2aa91ff2 S |
332 | |
333 | return $this; | |
334 | } | |
335 | ||
336 | /** | |
337 | * Registers a default plugin handler | |
338 | * | |
339 | * @param callable $callback class/method name | |
340 | * | |
ccd27f54 S |
341 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
342 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
343 | * @throws SmartyException if $callback is not callable |
344 | */ | |
345 | public function registerDefaultPluginHandler($callback) | |
346 | { | |
ccd27f54 | 347 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
2aa91ff2 | 348 | if (is_callable($callback)) { |
ccd27f54 | 349 | $smarty->default_plugin_handler_func = $callback; |
2aa91ff2 S |
350 | } else { |
351 | throw new SmartyException("Default plugin handler '$callback' not callable"); | |
352 | } | |
353 | ||
354 | return $this; | |
355 | } | |
356 | ||
357 | /** | |
358 | * Registers a default template handler | |
359 | * | |
360 | * @param callable $callback class/method name | |
361 | * | |
ccd27f54 S |
362 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
363 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
364 | * @throws SmartyException if $callback is not callable |
365 | */ | |
366 | public function registerDefaultTemplateHandler($callback) | |
367 | { | |
ccd27f54 | 368 | Smarty_Internal_Extension_DefaultTemplateHandler::registerDefaultTemplateHandler($this, $callback); |
2aa91ff2 S |
369 | return $this; |
370 | } | |
371 | ||
372 | /** | |
373 | * Registers a default template handler | |
374 | * | |
375 | * @param callable $callback class/method name | |
376 | * | |
ccd27f54 S |
377 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
378 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
379 | * @throws SmartyException if $callback is not callable |
380 | */ | |
381 | public function registerDefaultConfigHandler($callback) | |
382 | { | |
ccd27f54 | 383 | Smarty_Internal_Extension_DefaultTemplateHandler::registerDefaultConfigHandler($this, $callback); |
2aa91ff2 S |
384 | return $this; |
385 | } | |
386 | ||
387 | /** | |
388 | * Registers a filter function | |
389 | * | |
390 | * @param string $type filter type | |
391 | * @param callback $callback | |
392 | * | |
ccd27f54 S |
393 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
394 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
395 | */ |
396 | public function registerFilter($type, $callback) | |
397 | { | |
ccd27f54 S |
398 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
399 | $smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback; | |
2aa91ff2 S |
400 | |
401 | return $this; | |
402 | } | |
403 | ||
404 | /** | |
405 | * Unregisters a filter function | |
406 | * | |
407 | * @param string $type filter type | |
408 | * @param callback $callback | |
409 | * | |
ccd27f54 S |
410 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
411 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
412 | */ |
413 | public function unregisterFilter($type, $callback) | |
414 | { | |
415 | $name = $this->_get_filter_name($callback); | |
ccd27f54 S |
416 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
417 | if (isset($smarty->registered_filters[$type][$name])) { | |
418 | unset($smarty->registered_filters[$type][$name]); | |
2aa91ff2 S |
419 | } |
420 | ||
421 | return $this; | |
422 | } | |
423 | ||
424 | /** | |
425 | * Return internal filter name | |
426 | * | |
427 | * @param callback $function_name | |
428 | * | |
429 | * @return string internal filter name | |
430 | */ | |
431 | public function _get_filter_name($function_name) | |
432 | { | |
433 | if (is_array($function_name)) { | |
434 | $_class_name = (is_object($function_name[0]) ? | |
435 | get_class($function_name[0]) : $function_name[0]); | |
436 | ||
437 | return $_class_name . '_' . $function_name[1]; | |
438 | } else { | |
439 | return $function_name; | |
440 | } | |
441 | } | |
442 | ||
443 | /** | |
444 | * load a filter of specified type and name | |
445 | * | |
446 | * @param string $type filter type | |
447 | * @param string $name filter name | |
448 | * | |
449 | * @throws SmartyException if filter could not be loaded | |
450 | */ | |
451 | public function loadFilter($type, $name) | |
452 | { | |
ccd27f54 | 453 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
2aa91ff2 S |
454 | $_plugin = "smarty_{$type}filter_{$name}"; |
455 | $_filter_name = $_plugin; | |
ccd27f54 | 456 | if ($smarty->loadPlugin($_plugin)) { |
2aa91ff2 S |
457 | if (class_exists($_plugin, false)) { |
458 | $_plugin = array($_plugin, 'execute'); | |
459 | } | |
460 | if (is_callable($_plugin)) { | |
ccd27f54 | 461 | $smarty->registered_filters[$type][$_filter_name] = $_plugin; |
2aa91ff2 S |
462 | |
463 | return true; | |
464 | } | |
465 | } | |
466 | throw new SmartyException("{$type}filter \"{$name}\" not callable"); | |
467 | } | |
468 | ||
469 | /** | |
470 | * unload a filter of specified type and name | |
471 | * | |
472 | * @param string $type filter type | |
473 | * @param string $name filter name | |
474 | * | |
ccd27f54 S |
475 | * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or |
476 | * Smarty_Internal_Template) instance for chaining | |
2aa91ff2 S |
477 | */ |
478 | public function unloadFilter($type, $name) | |
479 | { | |
ccd27f54 | 480 | $smarty = isset($this->smarty) ? $this->smarty : $this; |
2aa91ff2 | 481 | $_filter_name = "smarty_{$type}filter_{$name}"; |
ccd27f54 S |
482 | if (isset($smarty->registered_filters[$type][$_filter_name])) { |
483 | unset ($smarty->registered_filters[$type][$_filter_name]); | |
2aa91ff2 S |
484 | } |
485 | ||
486 | return $this; | |
487 | } | |
488 | ||
489 | /** | |
490 | * preg_replace callback to convert camelcase getter/setter to underscore property names | |
491 | * | |
492 | * @param string $match match string | |
493 | * | |
494 | * @return string replacemant | |
495 | */ | |
496 | private function replaceCamelcase($match) | |
497 | { | |
498 | return "_" . strtolower($match[1]); | |
499 | } | |
500 | ||
501 | /** | |
502 | * Handle unknown class methods | |
503 | * | |
504 | * @param string $name unknown method-name | |
505 | * @param array $args argument array | |
506 | * | |
507 | * @throws SmartyException | |
508 | */ | |
509 | public function __call($name, $args) | |
510 | { | |
511 | static $_prefixes = array('set' => true, 'get' => true); | |
512 | static $_resolved_property_name = array(); | |
513 | static $_resolved_property_source = array(); | |
514 | ||
2aa91ff2 S |
515 | // see if this is a set/get for a property |
516 | $first3 = strtolower(substr($name, 0, 3)); | |
517 | if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') { | |
518 | if (isset($_resolved_property_name[$name])) { | |
519 | $property_name = $_resolved_property_name[$name]; | |
520 | } else { | |
521 | // try to keep case correct for future PHP 6.0 case-sensitive class methods | |
522 | // lcfirst() not available < PHP 5.3.0, so improvise | |
523 | $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); | |
524 | // convert camel case to underscored name | |
525 | $property_name = preg_replace_callback('/([A-Z])/', array($this, 'replaceCamelcase'), $property_name); | |
526 | $_resolved_property_name[$name] = $property_name; | |
527 | } | |
528 | if (isset($_resolved_property_source[$property_name])) { | |
ccd27f54 | 529 | $status = $_resolved_property_source[$property_name]; |
2aa91ff2 | 530 | } else { |
ccd27f54 | 531 | $status = null; |
2aa91ff2 | 532 | if (property_exists($this, $property_name)) { |
ccd27f54 | 533 | $status = true; |
2aa91ff2 | 534 | } elseif (property_exists($this->smarty, $property_name)) { |
ccd27f54 | 535 | $status = false; |
2aa91ff2 | 536 | } |
ccd27f54 | 537 | $_resolved_property_source[$property_name] = $status; |
2aa91ff2 | 538 | } |
ccd27f54 S |
539 | $smarty = null; |
540 | if ($status === true) { | |
541 | $smarty = $this; | |
542 | } elseif ($status === false) { | |
543 | $smarty = $this->smarty; | |
544 | } | |
545 | if ($smarty) { | |
2aa91ff2 | 546 | if ($first3 == 'get') { |
ccd27f54 | 547 | return $smarty->$property_name; |
2aa91ff2 | 548 | } else { |
ccd27f54 | 549 | return $smarty->$property_name = $args[0]; |
2aa91ff2 | 550 | } |
ccd27f54 S |
551 | } |
552 | throw new SmartyException("property '$property_name' does not exist."); | |
2aa91ff2 | 553 | } |
2aa91ff2 S |
554 | throw new SmartyException("Call of unknown method '$name'."); |
555 | } | |
556 | } | |
ccd27f54 | 557 |