From a86e405a0f055c387263a03b28f00c2c03ee7824 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 8 Oct 2023 15:11:28 +0900 Subject: [PATCH] feat: add FileLocatorCached class --- system/Autoloader/FileLocatorCached.php | 180 ++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 system/Autoloader/FileLocatorCached.php diff --git a/system/Autoloader/FileLocatorCached.php b/system/Autoloader/FileLocatorCached.php new file mode 100644 index 000000000000..55f0b7bc4b51 --- /dev/null +++ b/system/Autoloader/FileLocatorCached.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Autoloader; + +use CodeIgniter\Cache\CacheInterface; +use CodeIgniter\Cache\FactoriesCache\FileVarExportHandler; + +/** + * FileLocator with Cache + * + * There is no FileLocator interface, so this extends FileLocator. + */ +final class FileLocatorCached extends FileLocator +{ + private FileLocator $locator; + + /** + * @var CacheInterface|FileVarExportHandler + */ + private $cacheHandler; + + /** + * Cache data + * + * [method => data] + * E.g., + * [ + * 'search' => [$path => $foundPaths], + * ] + */ + private array $cache = []; + + /** + * Is the cache updated? + */ + private bool $cacheUpdated = false; + + private string $cacheKey = 'FileLocatorCache'; + + /** + * @param CacheInterface|FileVarExportHandler|null $cache + */ + public function __construct(FileLocator $locator, $cache = null) + { + // Do not call parent constructor. + + $this->cacheHandler = $cache ?? new FileVarExportHandler(); + $this->locator = $locator; + + $this->loadCache(); + } + + private function loadCache(): void + { + $data = $this->cacheHandler->get($this->cacheKey); + + if (is_array($data)) { + $this->cache = $data; + } + } + + public function __destruct() + { + $this->saveCache(); + } + + private function saveCache(): void + { + if ($this->cacheUpdated) { + $this->cacheHandler->save($this->cacheKey, $this->cache, 3600 * 24); + } + } + + protected function getNamespaces() + { + if (isset($this->cache['getNamespaces'])) { + return $this->cache['getNamespaces']; + } + + $namespaces = $this->locator->getNamespaces(); + + $this->cache['getNamespaces'] = $namespaces; + $this->cacheUpdated = true; + + return $namespaces; + } + + public function findQualifiedNameFromPath(string $path): false|string + { + if (isset($this->cache['findQualifiedNameFromPath'][$path])) { + return $this->cache['findQualifiedNameFromPath'][$path]; + } + + $classname = $this->locator->findQualifiedNameFromPath($path); + + $this->cache['findQualifiedNameFromPath'][$path] = $classname; + $this->cacheUpdated = true; + + return $classname; + } + + public function getClassname(string $file): string + { + if (isset($this->cache['getClassname'][$file])) { + return $this->cache['getClassname'][$file]; + } + + $classname = $this->locator->getClassname($file); + + $this->cache['getClassname'][$file] = $classname; + $this->cacheUpdated = true; + + return $classname; + } + + public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array + { + if (isset($this->cache['search'][$path][$ext][$prioritizeApp])) { + return $this->cache['search'][$path][$ext][$prioritizeApp]; + } + + $foundPaths = $this->locator->search($path, $ext, $prioritizeApp); + + $this->cache['search'][$path][$ext][$prioritizeApp] = $foundPaths; + $this->cacheUpdated = true; + + return $foundPaths; + } + + public function listFiles(string $path): array + { + if (isset($this->cache['listFiles'][$path])) { + return $this->cache['listFiles'][$path]; + } + + $files = $this->locator->listFiles($path); + + $this->cache['listFiles'][$path] = $files; + $this->cacheUpdated = true; + + return $files; + } + + public function listNamespaceFiles(string $prefix, string $path): array + { + if (isset($this->cache['listNamespaceFiles'][$prefix][$path])) { + return $this->cache['listNamespaceFiles'][$prefix][$path]; + } + + $files = $this->locator->listNamespaceFiles($prefix, $path); + + $this->cache['listNamespaceFiles'][$prefix][$path] = $files; + $this->cacheUpdated = true; + + return $files; + } + + public function locateFile(string $file, ?string $folder = null, string $ext = 'php') + { + if (isset($this->cache['locateFile'][$file][$folder][$ext])) { + return $this->cache['locateFile'][$file][$folder][$ext]; + } + + $files = $this->locator->locateFile($file, $folder, $ext); + + $this->cache['locateFile'][$file][$folder][$ext] = $files; + $this->cacheUpdated = true; + + return $files; + } +}