Complex classes like CachePlugin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use CachePlugin, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | final class CachePlugin implements Plugin |
||
28 | { |
||
29 | use VersionBridgePlugin; |
||
30 | |||
31 | /** |
||
32 | * @var CacheItemPoolInterface |
||
33 | */ |
||
34 | private $pool; |
||
35 | |||
36 | /** |
||
37 | * @var StreamFactory|StreamFactoryInterface |
||
38 | */ |
||
39 | private $streamFactory; |
||
40 | |||
41 | /** |
||
42 | * @var array |
||
43 | */ |
||
44 | private $config; |
||
45 | |||
46 | /** |
||
47 | * Cache directives indicating if a response can not be cached. |
||
48 | * |
||
49 | * @var array |
||
50 | */ |
||
51 | private $noCacheFlags = ['no-cache', 'private', 'no-store']; |
||
52 | |||
53 | /** |
||
54 | * @param CacheItemPoolInterface $pool |
||
55 | * @param StreamFactory|StreamFactoryInterface $streamFactory |
||
56 | * @param array $config { |
||
57 | * |
||
58 | * @var bool $respect_cache_headers Whether to look at the cache directives or ignore them |
||
59 | * @var int $default_ttl (seconds) If we do not respect cache headers or can't calculate a good ttl, use this |
||
60 | * value |
||
61 | * @var string $hash_algo The hashing algorithm to use when generating cache keys |
||
62 | * @var int $cache_lifetime (seconds) To support serving a previous stale response when the server answers 304 |
||
63 | * we have to store the cache for a longer time than the server originally says it is valid for. |
||
64 | * We store a cache item for $cache_lifetime + max age of the response. |
||
65 | * @var array $methods list of request methods which can be cached |
||
66 | * @var array $blacklisted_paths list of regex patterns of paths explicitly not to be cached |
||
67 | * @var array $respect_response_cache_directives list of cache directives this plugin will respect while caching responses |
||
68 | * @var CacheKeyGenerator $cache_key_generator an object to generate the cache key. Defaults to a new instance of SimpleGenerator |
||
69 | * @var CacheListener[] $cache_listeners an array of objects to act on the response based on the results of the cache check. |
||
70 | * Defaults to an empty array |
||
71 | * } |
||
72 | */ |
||
73 | 16 | public function __construct(CacheItemPoolInterface $pool, $streamFactory, array $config = []) |
|
94 | |||
95 | /** |
||
96 | * This method will setup the cachePlugin in client cache mode. When using the client cache mode the plugin will |
||
97 | * cache responses with `private` cache directive. |
||
98 | * |
||
99 | * @param CacheItemPoolInterface $pool |
||
100 | * @param StreamFactory|StreamFactoryInterface $streamFactory |
||
101 | * @param array $config For all possible config options see the constructor docs |
||
102 | * |
||
103 | * @return CachePlugin |
||
104 | */ |
||
105 | public static function clientCache(CacheItemPoolInterface $pool, $streamFactory, array $config = []) |
||
118 | |||
119 | /** |
||
120 | * This method will setup the cachePlugin in server cache mode. This is the default caching behavior it refuses to |
||
121 | * cache responses with the `private`or `no-cache` directives. |
||
122 | * |
||
123 | * @param CacheItemPoolInterface $pool |
||
124 | * @param StreamFactory|StreamFactoryInterface $streamFactory |
||
125 | * @param array $config For all possible config options see the constructor docs |
||
126 | * |
||
127 | * @return CachePlugin |
||
128 | */ |
||
129 | public static function serverCache(CacheItemPoolInterface $pool, $streamFactory, array $config = []) |
||
133 | |||
134 | protected function doHandleRequest(RequestInterface $request, callable $next, callable $first) |
||
216 | |||
217 | /** |
||
218 | * Calculate the timestamp when this cache item should be dropped from the cache. The lowest value that can be |
||
219 | * returned is $maxAge. |
||
220 | * |
||
221 | * @param int|null $maxAge |
||
222 | * |
||
223 | * @return int|null Unix system time passed to the PSR-6 cache |
||
224 | */ |
||
225 | private function calculateCacheItemExpiresAfter($maxAge) |
||
233 | |||
234 | /** |
||
235 | * Calculate the timestamp when a response expires. After that timestamp, we need to send a |
||
236 | * If-Modified-Since / If-None-Match request to validate the response. |
||
237 | * |
||
238 | * @param int|null $maxAge |
||
239 | * |
||
240 | * @return int|null Unix system time. A null value means that the response expires when the cache item expires |
||
241 | */ |
||
242 | private function calculateResponseExpiresAt($maxAge) |
||
250 | |||
251 | /** |
||
252 | * Verify that we can cache this response. |
||
253 | * |
||
254 | * @param ResponseInterface $response |
||
255 | * |
||
256 | * @return bool |
||
257 | */ |
||
258 | protected function isCacheable(ResponseInterface $response) |
||
273 | |||
274 | /** |
||
275 | * Verify that we can cache this request. |
||
276 | * |
||
277 | * @param RequestInterface $request |
||
278 | * |
||
279 | * @return bool |
||
280 | */ |
||
281 | private function isCacheableRequest(RequestInterface $request) |
||
291 | |||
292 | /** |
||
293 | * Get the value of a parameter in the cache control header. |
||
294 | * |
||
295 | * @param ResponseInterface $response |
||
296 | * @param string $name The field of Cache-Control to fetch |
||
297 | * |
||
298 | * @return bool|string The value of the directive, true if directive without value, false if directive not present |
||
299 | */ |
||
300 | private function getCacheControlDirective(ResponseInterface $response, $name) |
||
316 | |||
317 | /** |
||
318 | * @param RequestInterface $request |
||
319 | * |
||
320 | * @return string |
||
321 | */ |
||
322 | private function createCacheKey(RequestInterface $request) |
||
328 | |||
329 | /** |
||
330 | * Get a ttl in seconds. It could return null if we do not respect cache headers and got no defaultTtl. |
||
331 | * |
||
332 | * @param ResponseInterface $response |
||
333 | * |
||
334 | * @return int|null |
||
335 | */ |
||
336 | private function getMaxAge(ResponseInterface $response) |
||
361 | |||
362 | /** |
||
363 | * Configure an options resolver. |
||
364 | * |
||
365 | * @param OptionsResolver $resolver |
||
366 | */ |
||
367 | private function configureOptions(OptionsResolver $resolver) |
||
413 | |||
414 | /** |
||
415 | * @param CacheItemInterface $cacheItem |
||
416 | * |
||
417 | * @return ResponseInterface |
||
418 | */ |
||
419 | private function createResponseFromCacheItem(CacheItemInterface $cacheItem) |
||
437 | |||
438 | /** |
||
439 | * Get the value of the "If-Modified-Since" header. |
||
440 | * |
||
441 | * @param CacheItemInterface $cacheItem |
||
442 | * |
||
443 | * @return string|null |
||
444 | */ |
||
445 | private function getModifiedSinceHeaderValue(CacheItemInterface $cacheItem) |
||
458 | |||
459 | /** |
||
460 | * Get the ETag from the cached response. |
||
461 | * |
||
462 | * @param CacheItemInterface $cacheItem |
||
463 | * |
||
464 | * @return string|null |
||
465 | */ |
||
466 | private function getETag(CacheItemInterface $cacheItem) |
||
480 | |||
481 | /** |
||
482 | * Call the cache listeners, if they are set. |
||
483 | * |
||
484 | * @param RequestInterface $request |
||
485 | * @param ResponseInterface $response |
||
486 | * @param bool $cacheHit |
||
487 | * @param CacheItemInterface|null $cacheItem |
||
488 | * |
||
489 | * @return ResponseInterface |
||
490 | */ |
||
491 | private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, $cacheHit, $cacheItem) |
||
499 | } |
||
500 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.