Development

/branches/1.4/lib/filter/sfCacheFilter.class.php

You must first sign up to be able to contribute.

root/branches/1.4/lib/filter/sfCacheFilter.class.php

Revision 28625, 5.9 kB (checked in by Kris.Wallsmith, 5 years ago)

[1.3, 1.4] fixed broken reference to response in the cache filter when a page cache is found

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10
11 /**
12  * sfCacheFilter deals with page caching and action caching.
13  *
14  * @package    symfony
15  * @subpackage filter
16  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17  * @version    SVN: $Id$
18  */
19 class sfCacheFilter extends sfFilter
20 {
21   protected
22     $cacheManager = null,
23     $request      = null,
24     $response     = null,
25     $routing      = null,
26     $cache        = array();
27
28   /**
29    * Initializes this Filter.
30    *
31    * @param sfContext $context    The current application context
32    * @param array     $parameters An associative array of initialization parameters
33    *
34    * @return bool true, if initialization completes successfully, otherwise false
35    *
36    * @throws <b>sfInitializationException</b> If an error occurs while initializing this Filter
37    */
38   public function initialize($context, $parameters = array())
39   {
40     parent::initialize($context, $parameters);
41
42     $this->cacheManager = $context->getViewCacheManager();
43     $this->request      = $context->getRequest();
44     $this->response     = $context->getResponse();
45     $this->routing      = $context->getRouting();
46   }
47
48   /**
49    * Executes this filter.
50    *
51    * @param sfFilterChain $filterChain A sfFilterChain instance
52    */
53   public function execute($filterChain)
54   {
55     // execute this filter only once, if cache is set and no GET or POST parameters
56     if (!sfConfig::get('sf_cache'))
57     {
58       $filterChain->execute();
59
60       return;
61     }
62
63     if ($this->executeBeforeExecution())
64     {
65       $filterChain->execute();
66     }
67
68     $this->executeBeforeRendering();
69   }
70
71   public function executeBeforeExecution()
72   {
73     $uri = $this->cacheManager->getCurrentCacheKey();
74
75     if (null === $uri)
76     {
77       return true;
78     }
79
80     // page cache
81     $cacheable = $this->cacheManager->isCacheable($uri);
82     if ($cacheable && $this->cacheManager->withLayout($uri))
83     {
84       $inCache = $this->cacheManager->getPageCache($uri);
85       $this->cache[$uri] = $inCache;
86
87       if ($inCache)
88       {
89         // update the local response reference with the one pulled from the cache
90         $this->response = $this->context->getResponse();
91
92         // page is in cache, so no need to run execution filter
93         return false;
94       }
95     }
96
97     return true;
98   }
99
100   /**
101    * Executes this filter.
102    */
103   public function executeBeforeRendering()
104   {
105     // cache only 200 HTTP status
106     if (200 != $this->response->getStatusCode())
107     {
108       return;
109     }
110
111     $uri = $this->cacheManager->getCurrentCacheKey();
112
113     // save page in cache
114     if (isset($this->cache[$uri]) && false === $this->cache[$uri])
115     {
116       $this->setCacheExpiration($uri);
117       $this->setCacheValidation($uri);
118
119       // set Vary headers
120       foreach ($this->cacheManager->getVary($uri, 'page') as $vary)
121       {
122         $this->response->addVaryHttpHeader($vary);
123       }
124
125       $this->cacheManager->setPageCache($uri);
126     }
127
128     // cache validation
129     $this->checkCacheValidation();
130   }
131
132   /**
133    * Sets cache expiration headers.
134    *
135    * @param string $uri An internal URI
136    */
137   protected function setCacheExpiration($uri)
138   {
139     // don't add cache expiration (Expires) if
140     //   * the client lifetime is not set
141     //   * the response already has a cache validation (Last-Modified header)
142     //   * the Expires header has already been set
143     if (!$lifetime = $this->cacheManager->getClientLifeTime($uri, 'page'))
144     {
145       return;
146     }
147
148     if ($this->response->hasHttpHeader('Last-Modified'))
149     {
150       return;
151     }
152
153     if (!$this->response->hasHttpHeader('Expires'))
154     {
155       $this->response->setHttpHeader('Expires', $this->response->getDate(time() + $lifetime), false);
156       $this->response->addCacheControlHttpHeader('max-age', $lifetime);
157     }
158   }
159
160   /**
161    * Sets cache validation headers.
162    *
163    * @param string $uri An internal URI
164    */
165
166   protected function setCacheValidation($uri)
167   {
168     // don't add cache validation (Last-Modified) if
169     //   * the client lifetime is set (cache.yml)
170     //   * the response already has a Last-Modified header
171     if ($this->cacheManager->getClientLifeTime($uri, 'page'))
172     {
173       return;
174     }
175
176     if (!$this->response->hasHttpHeader('Last-Modified'))
177     {
178       $this->response->setHttpHeader('Last-Modified', $this->response->getDate(time()), false);
179     }
180
181     if (sfConfig::get('sf_etag'))
182     {
183       $etag = '"'.md5($this->response->getContent()).'"';
184       $this->response->setHttpHeader('ETag', $etag);
185     }
186   }
187
188   /**
189    * Checks cache validation headers.
190    */
191   protected function checkCacheValidation()
192   {
193     // Etag support
194     if (sfConfig::get('sf_etag'))
195     {
196       $etag = '"'.md5($this->response->getContent()).'"';
197
198       if ($this->request->getHttpHeader('IF_NONE_MATCH') == $etag)
199       {
200         $this->response->setStatusCode(304);
201         $this->response->setHeaderOnly(true);
202
203         if (sfConfig::get('sf_logging_enabled'))
204         {
205           $this->context->getEventDispatcher()->notify(new sfEvent($this, 'application.log', array('ETag matches If-None-Match (send 304)')));
206         }
207       }
208     }
209
210     // conditional GET support
211     // never in debug mode
212     if ($this->response->hasHttpHeader('Last-Modified') && (!sfConfig::get('sf_debug') || sfConfig::get('sf_test')))
213     {
214       $lastModified = $this->response->getHttpHeader('Last-Modified');
215       if ($this->request->getHttpHeader('IF_MODIFIED_SINCE') == $lastModified)
216       {
217         $this->response->setStatusCode(304);
218         $this->response->setHeaderOnly(true);
219
220         if (sfConfig::get('sf_logging_enabled'))
221         {
222           $this->context->getEventDispatcher()->notify(new sfEvent($this, 'application.log', array('Last-Modified matches If-Modified-Since (send 304)')));
223         }
224       }
225     }
226   }
227 }
228
Note: See TracBrowser for help on using the browser.