1<?php 2/** 3 * Smarty Resource Plugin 4 * 5 * @package Smarty 6 * @subpackage TemplateResources 7 * @author Rodney Rehm 8 */ 9 10/** 11 * Smarty Resource Plugin 12 * Base implementation for resource plugins 13 * 14 * @package Smarty 15 * @subpackage TemplateResources 16 * 17 * @method renderUncompiled(Smarty_Template_Source $source, Smarty_Internal_Template $_template) 18 * @method populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template) 19 * @method process(Smarty_Internal_Template $_smarty_tpl) 20 */ 21abstract class Smarty_Resource 22{ 23 /** 24 * resource types provided by the core 25 * 26 * @var array 27 */ 28 public static $sysplugins = array( 29 'file' => 'smarty_internal_resource_file.php', 30 'string' => 'smarty_internal_resource_string.php', 31 'extends' => 'smarty_internal_resource_extends.php', 32 'stream' => 'smarty_internal_resource_stream.php', 33 'eval' => 'smarty_internal_resource_eval.php', 34 'php' => 'smarty_internal_resource_php.php' 35 ); 36 37 /** 38 * Source is bypassing compiler 39 * 40 * @var boolean 41 */ 42 public $uncompiled = false; 43 44 /** 45 * Source must be recompiled on every occasion 46 * 47 * @var boolean 48 */ 49 public $recompiled = false; 50 51 /** 52 * Flag if resource does implement populateCompiledFilepath() method 53 * 54 * @var bool 55 */ 56 public $hasCompiledHandler = false; 57 58 /** 59 * Load Resource Handler 60 * 61 * @param Smarty $smarty smarty object 62 * @param string $type name of the resource 63 * 64 * @throws SmartyException 65 * @return Smarty_Resource Resource Handler 66 */ 67 public static function load(Smarty $smarty, $type) 68 { 69 // try smarty's cache 70 if (isset($smarty->_cache[ 'resource_handlers' ][ $type ])) { 71 return $smarty->_cache[ 'resource_handlers' ][ $type ]; 72 } 73 // try registered resource 74 if (isset($smarty->registered_resources[ $type ])) { 75 return $smarty->_cache[ 'resource_handlers' ][ $type ] = 76 $smarty->registered_resources[ $type ] instanceof Smarty_Resource ? 77 $smarty->registered_resources[ $type ] : new Smarty_Internal_Resource_Registered(); 78 } 79 // try sysplugins dir 80 if (isset(self::$sysplugins[ $type ])) { 81 $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type); 82 return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); 83 } 84 // try plugins dir 85 $_resource_class = 'Smarty_Resource_' . ucfirst($type); 86 if ($smarty->loadPlugin($_resource_class)) { 87 if (class_exists($_resource_class, false)) { 88 return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); 89 } else { 90 $smarty->registerResource( 91 $type, 92 array( 93 "smarty_resource_{$type}_source", "smarty_resource_{$type}_timestamp", 94 "smarty_resource_{$type}_secure", "smarty_resource_{$type}_trusted" 95 ) 96 ); 97 // give it another try, now that the resource is registered properly 98 return self::load($smarty, $type); 99 } 100 } 101 // try streams 102 $_known_stream = stream_get_wrappers(); 103 if (in_array($type, $_known_stream)) { 104 // is known stream 105 if (is_object($smarty->security_policy)) { 106 $smarty->security_policy->isTrustedStream($type); 107 } 108 return $smarty->_cache[ 'resource_handlers' ][ $type ] = new Smarty_Internal_Resource_Stream(); 109 } 110 // TODO: try default_(template|config)_handler 111 // give up 112 throw new SmartyException("Unknown resource type '{$type}'"); 113 } 114 115 /** 116 * extract resource_type and resource_name from template_resource and config_resource 117 * 118 * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including). 119 * 120 * @param string $resource_name template_resource or config_resource to parse 121 * @param string $default_resource the default resource_type defined in $smarty 122 * 123 * @return array with parsed resource name and type 124 */ 125 public static function parseResourceName($resource_name, $default_resource) 126 { 127 if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]/', $resource_name, $match)) { 128 $type = $match[ 1 ]; 129 $name = substr($resource_name, strlen($match[ 0 ])); 130 } else { 131 // no resource given, use default 132 // or single character before the colon is not a resource type, but part of the filepath 133 $type = $default_resource; 134 $name = $resource_name; 135 } 136 return array($name, $type); 137 } 138 139 /** 140 * modify template_resource according to resource handlers specifications 141 * 142 * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance 143 * @param string $template_resource template_resource to extract resource handler and 144 * name of 145 * 146 * @return string unique resource name 147 * @throws \SmartyException 148 */ 149 public static function getUniqueTemplateName($obj, $template_resource) 150 { 151 $smarty = $obj->_getSmartyObj(); 152 list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); 153 // TODO: optimize for Smarty's internal resource types 154 $resource = Smarty_Resource::load($smarty, $type); 155 // go relative to a given template? 156 $_file_is_dotted = $name[ 0 ] === '.' && ($name[ 1 ] === '.' || $name[ 1 ] === '/'); 157 if ($obj->_isTplObj() && $_file_is_dotted 158 && ($obj->source->type === 'file' || $obj->parent->source->type === 'extends') 159 ) { 160 $name = $smarty->_realpath(dirname($obj->parent->source->filepath) . DIRECTORY_SEPARATOR . $name); 161 } 162 return $resource->buildUniqueResourceName($smarty, $name); 163 } 164 165 /** 166 * initialize Source Object for given resource 167 * wrapper for backward compatibility to versions < 3.1.22 168 * Either [$_template] or [$smarty, $template_resource] must be specified 169 * 170 * @param Smarty_Internal_Template $_template template object 171 * @param Smarty $smarty smarty object 172 * @param string $template_resource resource identifier 173 * 174 * @return \Smarty_Template_Source Source Object 175 * @throws \SmartyException 176 */ 177 public static function source( 178 Smarty_Internal_Template $_template = null, 179 Smarty $smarty = null, 180 $template_resource = null 181 ) { 182 return Smarty_Template_Source::load($_template, $smarty, $template_resource); 183 } 184 185 /** 186 * Load template's source into current template object 187 * 188 * @param Smarty_Template_Source $source source object 189 * 190 * @return string template source 191 * @throws SmartyException if source cannot be loaded 192 */ 193 abstract public function getContent(Smarty_Template_Source $source); 194 195 /** 196 * populate Source Object with meta data from Resource 197 * 198 * @param Smarty_Template_Source $source source object 199 * @param Smarty_Internal_Template $_template template object 200 */ 201 abstract public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null); 202 203 /** 204 * populate Source Object with timestamp and exists from Resource 205 * 206 * @param Smarty_Template_Source $source source object 207 */ 208 public function populateTimestamp(Smarty_Template_Source $source) 209 { 210 // intentionally left blank 211 } 212 213 /** 214 * modify resource_name according to resource handlers specifications 215 * 216 * @param Smarty $smarty Smarty instance 217 * @param string $resource_name resource_name to make unique 218 * @param boolean $isConfig flag for config resource 219 * 220 * @return string unique resource name 221 */ 222 public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) 223 { 224 if ($isConfig) { 225 if (!isset($smarty->_joined_config_dir)) { 226 $smarty->getTemplateDir(null, true); 227 } 228 return get_class($this) . '#' . $smarty->_joined_config_dir . '#' . $resource_name; 229 } else { 230 if (!isset($smarty->_joined_template_dir)) { 231 $smarty->getTemplateDir(); 232 } 233 return get_class($this) . '#' . $smarty->_joined_template_dir . '#' . $resource_name; 234 } 235 } 236 237 /* 238 * Check if resource must check time stamps when when loading complied or cached templates. 239 * Resources like 'extends' which use source components my disable timestamp checks on own resource. 240 * 241 * @return bool 242 */ 243 /** 244 * Determine basename for compiled filename 245 * 246 * @param Smarty_Template_Source $source source object 247 * 248 * @return string resource's basename 249 */ 250 public function getBasename(Smarty_Template_Source $source) 251 { 252 return basename(preg_replace('![^\w]+!', '_', $source->name)); 253 } 254 255 /** 256 * @return bool 257 */ 258 public function checkTimestamps() 259 { 260 return true; 261 } 262} 263