Skip to content

Commit 4c8ab75

Browse files
committed
- Updated strictly return type hints in CacheManager
- Added CacheManager::getDriverList() - Added PhpfastcacheUnsupportedOperationException exception - Added deprecation section in migrating guide - Deprecated CacheManager::getStaticAllDrivers() - Deprecated CacheManager::getStaticSystemDrivers() - Deprecated configuration option "ignoreSymfonyNotice"
1 parent f08608c commit 4c8ab75

File tree

6 files changed

+237
-21
lines changed

6 files changed

+237
-21
lines changed

docs/migration/MigratingFromV6ToV7.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ The time has changed, you now have to use: `class PhpfastcacheAbstractProxy`
2121
For any useful purpose, all the PhpFastCache exceptions has been **C**apitalized.
2222
Class `Phpfastcache\Exceptions\phpFastCache[...]Exception` have been renamed to `Phpfastcache\Exceptions\Phpfastcache[...]Exception`
2323

24+
### Deprecations
25+
- `Phpfastcache\CacheManager::getStaticAllDrivers()` replaced by `Phpfastcache\CacheManager::getDriverList()`
26+
- `Phpfastcache\CacheManager::getStaticSystemDrivers()` replaced by `Phpfastcache\CacheManager::getDriverList()`
27+
- Configuration option `ignoreSymfonyNotice` will not be replaced since that the related Symfony notice in `Phpfastcache\CacheManager::getInstance()` has been removed
28+
2429
### Return type & Scalar type declarations
2530
:anger: :exclamation: The V7 will make use of new php's return type & scalars type declarations features.
2631
This means that you will now have to be very careful about the data types that you are sending to the phpFastCache API.
@@ -146,4 +151,3 @@ The API changelog used to be hardcoded as a HEREDOC in the `Api::getChangelog()`
146151
The API changelog format has been moved to a MarDown file (.md)
147152
If you were using `Api::getChangelog()` you may need to check that your code is still working as expected.
148153
The method still returns a valid string but its format has changed slightly.
149-

lib/Phpfastcache/CacheManager.php

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
use Phpfastcache\Config\ConfigurationOption;
1919
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
2020
use Phpfastcache\Exceptions\{
21-
PhpfastcacheDeprecatedException, PhpfastcacheDriverCheckException, PhpfastcacheDriverNotFoundException, PhpfastcacheInstanceNotFoundException, PhpfastcacheInvalidArgumentException, PhpfastcacheInvalidConfigurationException
21+
PhpfastcacheDeprecatedException, PhpfastcacheDriverCheckException, PhpfastcacheDriverNotFoundException, PhpfastcacheInstanceNotFoundException, PhpfastcacheInvalidArgumentException, PhpfastcacheInvalidConfigurationException, PhpfastcacheLogicException, PhpfastcacheUnsupportedOperationException
2222
};
23+
use Phpfastcache\Util\ClassNamespaceResolverTrait;
2324

2425
/**
2526
* Class CacheManager
@@ -51,6 +52,8 @@
5152
*/
5253
class CacheManager
5354
{
55+
use ClassNamespaceResolverTrait;
56+
5457
/**
5558
* @var ConfigurationOption
5659
*/
@@ -88,7 +91,7 @@ class CacheManager
8891
* @throws PhpfastcacheDriverNotFoundException
8992
* @throws PhpfastcacheInvalidArgumentException
9093
*/
91-
public static function getInstance($driver = 'auto', $config = null, $instanceId = null)
94+
public static function getInstance($driver = 'auto', $config = null, $instanceId = null): ExtendedCacheItemPoolInterface
9295
{
9396
static $badPracticeOmeter = [];
9497

@@ -202,17 +205,17 @@ public static function &getInternalInstances(): array
202205
}
203206

204207
/**
205-
* @todo Does we really keep it ??
206-
* @param $config
208+
* @param ConfigurationOption $config
207209
* @return string
208210
* @throws PhpfastcacheDriverCheckException
211+
* @throws \Phpfastcache\Exceptions\PhpfastcacheLogicException
209212
*/
210-
public static function getAutoClass(array $config = [])
213+
public static function getAutoClass(ConfigurationOption $config): string
211214
{
212215
static $autoDriver;
213216

214217
if ($autoDriver === null) {
215-
foreach (self::getStaticSystemDrivers() as $driver) {
218+
foreach (self::getDriverList() as $driver) {
216219
try {
217220
self::getInstance($driver, $config);
218221
$autoDriver = $driver;
@@ -223,15 +226,19 @@ public static function getAutoClass(array $config = [])
223226
}
224227
}
225228

229+
if(!$autoDriver || !\is_string($autoDriver)){
230+
throw new PhpfastcacheLogicException('Unable to find out a valid driver automatically');
231+
}
232+
226233
return $autoDriver;
227234
}
228235

229236
/**
230237
* @param string $name
231238
* @param array $arguments
232-
* @return \Psr\Cache\CacheItemPoolInterface
239+
* @return \Psr\Cache\ExtendedCacheItemPoolInterface
233240
*/
234-
public static function __callStatic($name, $arguments)
241+
public static function __callStatic(string $name, array $arguments): ExtendedCacheItemPoolInterface
235242
{
236243
$options = (\array_key_exists(0, $arguments) && \is_array($arguments) ? $arguments[ 0 ] : []);
237244

@@ -241,7 +248,7 @@ public static function __callStatic($name, $arguments)
241248
/**
242249
* @return bool
243250
*/
244-
public static function clearInstances()
251+
public static function clearInstances(): bool
245252
{
246253
self::$instances = [];
247254

@@ -252,9 +259,17 @@ public static function clearInstances()
252259
/**
253260
* @return string
254261
*/
255-
public static function getNamespacePath()
262+
public static function getNamespacePath(): string
263+
{
264+
return self::$namespacePath ?: self::getDefaultNamespacePath();
265+
}
266+
267+
/**
268+
* @return string
269+
*/
270+
public static function getDefaultNamespacePath(): string
256271
{
257-
return self::$namespacePath ?: __NAMESPACE__ . '\Drivers\\';
272+
return __NAMESPACE__ . '\Drivers\\';
258273
}
259274

260275
/**
@@ -283,12 +298,11 @@ public static function getDefaultConfig(): ConfigurationOption
283298

284299
/**
285300
* @return array
301+
* @deprecated As of V7 will be removed soon or later, use CacheManager::getDriverList() instead
286302
*/
287-
public static function getStaticSystemDrivers()
303+
public static function getStaticSystemDrivers(): array
288304
{
289-
/**
290-
* @todo Reflection reader
291-
*/
305+
trigger_error(sprintf('Method "%s" is deprecated as of the V7 and will be removed soon or later, use CacheManager::getDriverList() instead.', __METHOD__), E_USER_DEPRECATED);
292306
return [
293307
'Apc',
294308
'Apcu',
@@ -316,19 +330,45 @@ public static function getStaticSystemDrivers()
316330

317331
/**
318332
* @return array
333+
* @deprecated As of V7 will be removed soon or later, use CacheManager::getDriverList() instead
319334
*/
320-
public static function getStaticAllDrivers()
335+
public static function getStaticAllDrivers(): array
321336
{
322-
/**
323-
* @todo Reflection reader
324-
*/
337+
trigger_error(sprintf('Method "%s" is deprecated as of the V7 and will be removed soon or later, use CacheManager::getDriverList() instead.', __METHOD__), E_USER_DEPRECATED);
325338
return \array_merge(self::getStaticSystemDrivers(), [
326339
'Devtrue',
327340
'Devfalse',
328341
'Cookie',
329342
]);
330343
}
331344

345+
/**
346+
* @return string[]
347+
* @throws PhpfastcacheUnsupportedOperationException
348+
*/
349+
public static function getDriverList(): array
350+
{
351+
static $driverList;
352+
353+
if(self::getDefaultNamespacePath() === self::getNamespacePath()){
354+
if($driverList === null){
355+
$prefix = 'Phpfastcache\Drivers\\';
356+
$classMap = self::createClassMap(__DIR__ . '/Drivers');
357+
$driverList = [];
358+
359+
foreach ($classMap as $class => $file) {
360+
$driverList[] = str_replace($prefix, '', substr($class, 0, strrpos($class, '\\') ));
361+
}
362+
363+
$driverList = array_values(array_unique($driverList));
364+
}
365+
366+
return $driverList;
367+
}
368+
369+
throw new PhpfastcacheUnsupportedOperationException('Cannot get the driver list if the default namespace path has changed.');
370+
}
371+
332372
/**
333373
* @param string $driverName
334374
* @return string

lib/Phpfastcache/Config/ConfigurationOption.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,18 @@ public function setAutoTmpFallback(bool $autoTmpFallback): self
200200

201201
/**
202202
* @return bool
203+
* @deprecated As of V7
203204
*/
204205
public function isIgnoreSymfonyNotice(): bool
205206
{
207+
206208
return $this->ignoreSymfonyNotice;
207209
}
208210

209211
/**
210212
* @param bool $ignoreSymfonyNotice
211213
* @return ConfigurationOption
214+
* @deprecated As of V7
212215
*/
213216
public function setIgnoreSymfonyNotice(bool $ignoreSymfonyNotice): self
214217
{
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
*
4+
* This file is part of phpFastCache.
5+
*
6+
* @license MIT License (MIT)
7+
*
8+
* For full copyright and license information, please see the docs/CREDITS.txt file.
9+
*
10+
* @author Khoa Bui (khoaofgod) <[email protected]> http://www.phpfastcache.com
11+
* @author Georges.L (Geolim4) <[email protected]>
12+
*
13+
*/
14+
declare(strict_types=1);
15+
16+
namespace Phpfastcache\Exceptions;
17+
18+
/**
19+
* Class PhpfastcacheUnsupportedOperationException
20+
* @package Phpfastcache\Exceptions
21+
*/
22+
class PhpfastcacheUnsupportedOperationException extends PhpfastcacheRootException
23+
{
24+
25+
}

lib/Phpfastcache/Util/ClassNamespaceResolverTrait.php

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,122 @@ trait ClassNamespaceResolverTrait
2929
/**
3030
* @return string
3131
*/
32-
protected function getClassNamespace()
32+
protected function getClassNamespace(): string
3333
{
3434
if (!$this->namespace) {
3535
$this->namespace = \substr(static::class, 0, strrpos(static::class, '\\'));
3636
}
3737

3838
return $this->namespace;
3939
}
40+
41+
/**
42+
* Iterate over all files in the given directory searching for classes.
43+
*
44+
* NOTICE: This method has been borrowed from Symfony ClassLoader 3.4 since they
45+
* deprecated the whole component as of SF4. Our thanks to them.
46+
*
47+
* @param \Iterator|string|array $dir The directory to search in or an iterator
48+
*
49+
* @return array A class map array
50+
*/
51+
protected static function createClassMap($dir): array
52+
{
53+
if (\is_string($dir)) {
54+
$dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
55+
}
56+
$map = [];
57+
58+
if(\is_array($dir) || $dir instanceof \Traversable){
59+
foreach ($dir as $file) {
60+
if (!$file->isFile()) {
61+
continue;
62+
}
63+
$path = $file->getRealPath() ?: $file->getPathname();
64+
if ('php' !== pathinfo($path, PATHINFO_EXTENSION)) {
65+
continue;
66+
}
67+
$classes = self::findClasses($path);
68+
if (\PHP_VERSION_ID >= 70000) {
69+
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
70+
gc_mem_caches();
71+
}
72+
foreach ($classes as $class) {
73+
$map[ $class ] = $path;
74+
}
75+
}
76+
}
77+
78+
return $map;
79+
}
80+
81+
/**
82+
* Extract the classes in the given file.
83+
*
84+
* NOTICE: This method has been borrowed from Symfony ClassLoader 3.4 since they
85+
* deprecated the whole component as of SF4. Our thanks to them.
86+
*
87+
* @param string $path The file to check
88+
*
89+
* @return array The found classes
90+
*/
91+
protected static function findClasses(string $path): array
92+
{
93+
$contents = file_get_contents($path);
94+
$tokens = token_get_all($contents);
95+
$classes = [];
96+
$namespace = '';
97+
for ($i = 0; isset($tokens[ $i ]); ++$i) {
98+
$token = $tokens[ $i ];
99+
if (!isset($token[ 1 ])) {
100+
continue;
101+
}
102+
$class = '';
103+
switch ($token[ 0 ]) {
104+
case T_NAMESPACE:
105+
$namespace = '';
106+
// If there is a namespace, extract it
107+
while (isset($tokens[ ++$i ][ 1 ])) {
108+
if (in_array($tokens[ $i ][ 0 ], [T_STRING, T_NS_SEPARATOR])) {
109+
$namespace .= $tokens[ $i ][ 1 ];
110+
}
111+
}
112+
$namespace .= '\\';
113+
break;
114+
case T_CLASS:
115+
case T_INTERFACE:
116+
case T_TRAIT:
117+
// Skip usage of ::class constant
118+
$isClassConstant = false;
119+
for ($j = $i - 1; $j > 0; --$j) {
120+
if (!isset($tokens[ $j ][ 1 ])) {
121+
break;
122+
}
123+
if (T_DOUBLE_COLON === $tokens[ $j ][ 0 ]) {
124+
$isClassConstant = true;
125+
break;
126+
} elseif (!\in_array($tokens[ $j ][ 0 ], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT], false)) {
127+
break;
128+
}
129+
}
130+
if ($isClassConstant) {
131+
break;
132+
}
133+
// Find the classname
134+
while (isset($tokens[ ++$i ][ 1 ])) {
135+
$t = $tokens[ $i ];
136+
if (T_STRING === $t[ 0 ]) {
137+
$class .= $t[ 1 ];
138+
} elseif ('' !== $class && T_WHITESPACE === $t[ 0 ]) {
139+
break;
140+
}
141+
}
142+
$classes[] = ltrim($namespace . $class, '\\');
143+
break;
144+
default:
145+
break;
146+
}
147+
}
148+
return $classes;
149+
}
40150
}

tests/DriverListResolver.test.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/**
4+
* @author Khoa Bui (khoaofgod) <[email protected]> http://www.phpfastcache.com
5+
* @author Georges.L (Geolim4) <[email protected]>
6+
*/
7+
8+
use Phpfastcache\CacheManager;
9+
use Phpfastcache\Helper\TestHelper;
10+
11+
chdir(__DIR__);
12+
require_once __DIR__ . '/../lib/Phpfastcache/Autoload/Autoload.php';
13+
$testHelper = new TestHelper('Driver list resolver');
14+
15+
$subClasses = [
16+
'Config',
17+
'Driver',
18+
'Item',
19+
];
20+
21+
$driverList = CacheManager::getDriverList();
22+
23+
foreach ($driverList as $driver) {
24+
foreach ($subClasses as $subClass) {
25+
$className = "Phpfastcache\\Drivers\\{$driver}\\{$subClass}";
26+
if(class_exists($className)){
27+
$testHelper->printPassText(sprintf('Found the %s %s class: "%s"', $driver, $subClass, $className));
28+
}else{
29+
$testHelper->printFailText(sprintf('Class "%s" not found', $className));
30+
}
31+
}
32+
}
33+
34+
$testHelper->terminateTest();

0 commit comments

Comments
 (0)