Changeset 7787
- Timestamp:
- 03/09/08 17:38:15 (6 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.1/lib/view/sfViewCacheManager.class.php
r7724 r7787 59 59 // cache instance 60 60 $this->cache = $cache; 61 62 // r egister a named route for our partial cache (at the end)61 62 // routing instance 63 63 $this->routing = $context->getRouting(); 64 if (!$this->routing->hasRouteName('sf_cache_partial'))65 {66 $this->routing->connect('sf_cache_partial', '/sf_cache_partial/:module/:action/:sf_cache_key.', array(), array());67 }68 64 } 69 65 … … 90 86 /** 91 87 * Generates a unique cache key for an internal URI. 92 * 93 * @param string The internal unified resource identifier. 88 * This cache key can be used by any of the cache engines as a unique identifier to a cached resource 89 * 90 * Basically, the cache key generated for the following internal URI: 91 * module/action?key1=value1&key2=value2 92 * Looks like: 93 * /localhost/all/module/action/key1/value1/key2/value2 94 * 95 * @param string The internal unified resource identifier 96 * Accepts rules formatted like 'module/action?key1=value1&key2=value2' 97 * Does not accept rules starting with a route name, except for '@sf_cache_partial' 98 * @param string The host name 99 * Optional - defaults to the current host name bu default 100 * @param string The vary headers, separated by |, or "all" for all vary headers 101 * Defaults to 'all' 102 * @param string The contextual prefix for contextual partials. 103 * Defaults to 'currentModule/currentAction/currentPAram1/currentvalue1' 104 * Used only by the sfViewCacheManager::remove() method 94 105 * 95 106 * @return string The cache key 96 */ 97 public function generateCacheKey($internalUri) 107 * If some of the parameters contained wildcards (* or **), the generated key will also have wildcards 108 */ 109 public function generateCacheKey($internalUri, $hostName = '', $vary = '', $contextualPrefix = '') 98 110 { 99 111 if ($callable = sfConfig::get('sf_cache_namespace_callable')) … … 104 116 } 105 117 106 return call_user_func($callable, $internalUri); 107 } 108 109 // generate uri 110 // we want our URL with / only 111 $oldUrlFormat = sfConfig::get('sf_url_format'); 112 sfConfig::set('sf_url_format', 'PATH'); 118 return call_user_func($callable, $internalUri, $hostName, $vary); 119 } 120 121 if (strpos($internalUri, '@') === 0 && strpos($internalUri, '@sf_cache_partial') === false) 122 { 123 throw new sfException('A cache key cannot be generated for an internal URI using the @rule syntax'); 124 } 125 126 $cacheKey = ''; 127 113 128 if ($this->isContextual($internalUri)) 114 129 { 130 // Contextual partial 131 if(!$contextualPrefix) 132 { 133 list($route_name, $params) = $this->controller->convertUrlStringToParameters($this->routing->getCurrentInternalUri()); 134 $cacheKey = $this->convertParametersToKey($params); 135 } 136 else 137 { 138 $cacheKey = $contextualPrefix; 139 } 115 140 list($route_name, $params) = $this->controller->convertUrlStringToParameters($internalUri); 116 $ uri = $this->controller->genUrl($this->routing->getCurrentInternalUri()).sprintf('/%s/%s/%s', $params['module'], $params['action'], $params['sf_cache_key']);141 $cacheKey .= sprintf('/%s/%s/%s', $params['module'], $params['action'], $params['sf_cache_key']); 117 142 } 118 143 else 119 144 { 120 $uri = $this->controller->genUrl($internalUri); 121 } 122 sfConfig::set('sf_url_format', $oldUrlFormat); 123 145 // Regular action or non-contextual partial 146 list($route_name, $params) = $this->controller->convertUrlStringToParameters($internalUri); 147 if ($route_name == 'sf_cache_partial') 148 { 149 $cacheKey = 'sf_cache_partial/'; 150 } 151 $cacheKey .= $this->convertParametersToKey($params); 152 } 153 124 154 // prefix with vary headers 125 $varyHeaders = $this->getVary($internalUri); 126 if ($varyHeaders) 127 { 128 sort($varyHeaders); 155 if (!$vary) 156 { 157 $varyHeaders = $this->getVary($internalUri); 158 if ($varyHeaders) 159 { 160 sort($varyHeaders); 161 $request = $this->context->getRequest(); 162 $vary = ''; 163 164 foreach ($varyHeaders as $header) 165 { 166 $vary .= $request->getHttpHeader($header).'|'; 167 } 168 169 $vary = $vary; 170 } 171 else 172 { 173 $vary = 'all'; 174 } 175 } 176 177 // prefix with hostname 178 if (!$hostName) 179 { 129 180 $request = $this->context->getRequest(); 130 $vary = ''; 131 132 foreach ($varyHeaders as $header) 133 { 134 $vary .= $request->getHttpHeader($header).'|'; 135 } 136 137 $vary = $vary; 138 } 139 else 140 { 141 $vary = 'all'; 142 } 143 144 // prefix with hostname 145 $request = $this->context->getRequest(); 146 $hostName = $request->getHost(); 147 $hostName = preg_replace('/[^a-z0-9]/i', '_', $hostName); 148 $hostName = strtolower(preg_replace('/_+/', '_', $hostName)); 149 150 $uri = '/'.$hostName.'/'.$vary.'/'.$uri; 181 $hostName = $request->getHost(); 182 $hostName = preg_replace('/[^a-z0-9]/i', '_', $hostName); 183 $hostName = strtolower(preg_replace('/_+/', '_', $hostName)); 184 } 185 186 $cacheKey = sprintf('/%s/%s/%s', $hostName, $vary, $cacheKey); 151 187 152 188 // replace multiple / 153 $uri = preg_replace('#/+#', '/', $uri); 154 155 return $uri; 156 } 157 189 $cacheKey = preg_replace('#/+#', '/', $cacheKey); 190 191 return $cacheKey; 192 } 193 194 /** 195 * Transforms an associative array of parameters from an URI into a unique key 196 * 197 * @param Array Associative array of parameters from the URI (including, at least, module and action) 198 * 199 * @return String Unique key 200 */ 201 protected function convertParametersToKey($params) 202 { 203 if(!isset($params['module']) || !isset($params['action'])) 204 { 205 throw new sfException('A cache key must contain both a module and an action parameter'); 206 } 207 $module = $params['module']; 208 unset($params['module']); 209 $action = $params['action']; 210 unset($params['action']); 211 ksort($params); 212 $cacheKey = sprintf('%s/%s', $module, $action); 213 foreach ($params as $key => $value) 214 { 215 $cacheKey .= sprintf('/%s/%s', $key, $value); 216 } 217 218 return $cacheKey; 219 } 220 158 221 /** 159 222 * Adds a cache to the manager. … … 407 470 * 408 471 * @param string Internal uniform resource identifier 409 * 410 * @return boolean true, if the remove happend otherwise false 411 */ 412 public function remove($internalUri) 472 * @param string The host name 473 * @param string The vary headers, separated by |, or "all" for all vary headers 474 * @param string The removal prefix for contextual partials. Deauls to '**' (all actions, all params) 475 * 476 * @return boolean true, if the remove happened, false otherwise 477 */ 478 public function remove($internalUri, $hostName = '', $vary = '', $contextualPrefix = '**') 413 479 { 414 480 if (sfConfig::get('sf_logging_enabled')) … … 416 482 $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Remove cache for "%s"', $internalUri)))); 417 483 } 418 419 $key = $this->generateCacheKey($internalUri); 420 if ($this->cache->has($key)) 421 { 422 $this->cache->remove($key); 484 485 $cacheKey = $this->generateCacheKey($internalUri, $hostName, $vary, $contextualPrefix); 486 487 if(strpos($cacheKey, '*')) 488 { 489 return $this->cache->removePattern($cacheKey); 490 } 491 elseif ($this->cache->has($cacheKey)) 492 { 493 return $this->cache->remove($cacheKey); 423 494 } 424 495 } branches/1.1/test/unit/view/sfViewCacheManagerTest.php
r4957 r7787 12 12 require_once($_test_dir.'/unit/sfContextMock.class.php'); 13 13 14 $t = new lime_test( 11, new lime_output_color());14 $t = new lime_test(33, new lime_output_color()); 15 15 16 16 class myController extends sfWebController … … 61 61 public function removePattern($pattern, $delimiter = ':') 62 62 { 63 $pattern = '#^' . str_replace('*', '.*', $pattern) . '$#'; 64 foreach(self::$cache as $key => $value) 65 { 66 if(preg_match($pattern, $key)) 67 { 68 unset(self::$cache[$key]); 69 } 70 } 71 } 72 73 public function clean($mode = sfCache::ALL) 74 { 63 75 self::$cache = array(); 64 76 } 65 77 66 public function clean($mode = sfCache::ALL) 78 public function getTimeout($key) 79 { 80 return time() - 60; 81 } 82 83 public function getLastModified($key) 84 { 85 return time() - 600; 86 } 87 88 static public function clear() 67 89 { 68 90 self::$cache = array(); 69 91 } 70 71 public function getTimeout($key) 72 { 73 return time() - 60; 74 } 75 76 public function getLastModified($key) 77 { 78 return time() - 600; 79 } 80 81 static public function clear() 82 { 83 self::$cache = array(); 84 } 85 } 86 87 $context = sfContext::getInstance(array('controller' => 'myController', 'routing' => 'sfPatternRouting', 'request' => 'myRequest')); 92 } 93 94 class myRouting extends sfPatternRouting 95 { 96 public function getCurrentInternalUri($with_route_name = false) 97 { 98 return 'currentModule/currentAction?currentKey=currentValue'; 99 } 100 } 101 102 $context = sfContext::getInstance(array('controller' => 'myController', 'routing' => 'myRouting', 'request' => 'myRequest')); 88 103 89 104 $r = $context->routing; … … 95 110 $t->is($m->getCache(), $cache, '->initialize() takes a sfCache object as its second argument'); 96 111 112 // ->generateCacheKey() 113 $t->diag('->generateCacheKey'); 114 $t->is($m->generateCacheKey('mymodule/myaction'), '/localhost/all/mymodule/myaction', '->generateCacheKey() creates a simple cache key from an internal URI'); 115 $t->is($m->generateCacheKey('mymodule/myaction', 'foo'), '/foo/all/mymodule/myaction', '->generateCacheKey() can take a hostName as second parameter'); 116 $t->is($m->generateCacheKey('mymodule/myaction', null, 'bar'), '/localhost/bar/mymodule/myaction', '->generateCacheKey() can take a serialized set of vary headers as third parameter'); 117 118 $t->is($m->generateCacheKey('mymodule/myaction?key1=value1&key2=value2'), '/localhost/all/mymodule/myaction/key1/value1/key2/value2', '->generateCacheKey() includes request parameters as key/value pairs'); 119 $t->is($m->generateCacheKey('mymodule/myaction?akey=value1&ckey=value2&bkey=value3'), '/localhost/all/mymodule/myaction/akey/value1/bkey/value3/ckey/value2', '->generateCacheKey() reorders request parameters alphabetically'); 120 121 try 122 { 123 $m->generateCacheKey('@rule?key=value'); 124 $t->fail('->generateCacheKey() throws an sfException when passed an internal URI with a rule'); 125 } 126 catch(sfException $e) 127 { 128 $t->pass('->generateCacheKey() throws an sfException when passed an internal URI with a rule'); 129 } 130 try 131 { 132 $m->generateCacheKey('@sf_cache_partial?module=mymodule&action=myaction'); 133 $t->pass('->generateCacheKey() does not throw an sfException when passed an internal URI with a @sf_cache_partial rule'); 134 } 135 catch(sfException $e) 136 { 137 $t->fail('->generateCacheKey() does not throw an sfException when passed an internal URI with a @sf_cache_partial rule'); 138 } 139 try 140 { 141 $m->generateCacheKey('@sf_cache_partial?key=value'); 142 $t->fail('->generateCacheKey() throws an sfException when passed an internal URI with a @sf_cache_partial rule with no module or action param'); 143 } 144 catch(sfException $e) 145 { 146 $t->pass('->generateCacheKey() throws an sfException when passed an internal URI with a @sf_cache_partial rule with no module or action param'); 147 } 148 149 $t->is($m->generateCacheKey('@sf_cache_partial?module=foo&action=bar&sf_cache_key=value'), '/localhost/all/sf_cache_partial/foo/bar/sf_cache_key/value', '->generateCacheKey() can deal with internal URIs to partials'); 150 151 $m = get_cache_manager($context); 152 $m->addCache('foo', 'bar', get_cache_config(true)); 153 $t->is($m->generateCacheKey('@sf_cache_partial?module=foo&action=bar&sf_cache_key=value'), '/localhost/all/currentModule/currentAction/currentKey/currentValue/foo/bar/value', '->generateCacheKey() can deal with internal URIs to contextual partials'); 154 155 $t->is($m->generateCacheKey('@sf_cache_partial?module=foo&action=bar&sf_cache_key=value', null, null, 'baz'), '/localhost/all/baz/foo/bar/value', '->generateCacheKey() can take a prefix for contextual partials as fourth parameter'); 156 157 97 158 // ->generateNamespace() 98 159 $t->diag('->generateNamespace()'); … … 116 177 $t->is($m->set('test', 'module/action'), true, '->set() returns true if the action is cacheable'); 117 178 179 $m = get_cache_manager($context); 180 $m->addCache('module', 'action', get_cache_config()); 181 $m->set('test', 'module/action'); 182 $t->is($m->get('module/action'), 'test', '->set() stores the first parameter in a key computed from the second parameter'); 183 184 $m = get_cache_manager($context); 185 $m->addCache('module', 'action', get_cache_config()); 186 $m->set('test', 'module/action?key1=value1'); 187 $t->is($m->get('module/action?key1=value1'), 'test', '->set() works with URIs with parameters'); 188 $t->is($m->get('module/action?key2=value2'), null, '->set() stores a different version for each set of parameters'); 189 $t->is($m->get('module/action'), null, '->set() stores a different version for each set of parameters'); 190 191 $m = get_cache_manager($context); 192 $m->addCache('module', 'action', get_cache_config()); 193 $m->set('test', '@sf_cache_partial?module=module&action=action'); 194 $t->is($m->get('@sf_cache_partial?module=module&action=action'), 'test', '->set() accepts keys to partials'); 195 196 $m = get_cache_manager($context); 197 $m->addCache('module', 'action', get_cache_config(true)); 198 $m->set('test', '@sf_cache_partial?module=module&action=action'); 199 $t->is($m->get('@sf_cache_partial?module=module&action=action'), 'test', '->set() accepts keys to contextual partials'); 200 118 201 // ->get() 119 202 $t->diag('->get()'); … … 141 224 $t->is($m->has('module/action'), false, '->remove() removes cache content for an action'); 142 225 226 $m->set('test', 'module/action?key1=value1'); 227 $m->set('test', 'module/action?key2=value2'); 228 $m->remove('module/action?key1=value1'); 229 $t->is($m->has('module/action?key1=value1'), false, '->remove() removes accepts an internal URI as first parameter'); 230 $t->is($m->has('module/action?key2=value2'), true, '->remove() does not remove cache content for keys not matching the internal URI'); 231 232 $m = get_cache_manager($context); 233 $m->addCache('module', 'action', get_cache_config()); 234 $m->set('test', 'module/action?key1=value1'); 235 $m->set('test', 'module/action?key1=value2'); 236 $m->set('test', 'module/action?key2=value1'); 237 $m->remove('module/action?key1=*'); 238 $t->is($m->has('module/action?key1=value1'), false, '->remove() accepts wildcards in URIs and then removes all keys matching the pattern'); 239 $t->is($m->has('module/action?key1=value2'), false, '->remove() accepts wildcards in URIs and then removes all keys matching the pattern'); 240 $t->is($m->has('module/action?key2=value1'), true, '->remove() accepts wildcards in URIs and lets keys not matching the pattern unchanged'); 241 143 242 function get_cache_manager($context) 144 243 { … … 149 248 } 150 249 151 function get_cache_config( )250 function get_cache_config($contextual = false) 152 251 { 153 252 return array( … … 155 254 'lifeTime' => 86400, 156 255 'clientLifeTime' => 86400, 157 'contextual' => false,256 'contextual' => $contextual, 158 257 'vary' => array(), 159 258 );