Skip to content

Commit

Permalink
feat!: FileLocator caching
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjis committed Oct 6, 2023
1 parent edfa0b5 commit f890ccb
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 4 deletions.
103 changes: 99 additions & 4 deletions system/Autoloader/FileLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace CodeIgniter\Autoloader;

use CodeIgniter\Cache\FileLocatorCache;

/**
* Allows loading non-class files in a namespaced manner.
* Works with Helpers, Views, etc.
Expand All @@ -26,9 +28,40 @@ class FileLocator
*/
protected $autoloader;

public function __construct(Autoloader $autoloader)
/**
* Cache
*
* [method => data]
* E.g.,
* [
* 'search' => [$path => $foundPaths],
* ]
*/
protected array $cache = [];

/**
* Is the cache updated?
*/
protected bool $cacheUpdated = false;

private ?FileLocatorCache $locatorCache;

public function __construct(Autoloader $autoloader, ?FileLocatorCache $cache = null)
{
$this->autoloader = $autoloader;
$this->locatorCache = $cache;

if ($cache !== null) {
$this->locatorCache->setLocator($this);
$this->locatorCache->load();
}
}

public function __destruct()
{
$this->autoloader = $autoloader;
if ($this->locatorCache !== null) {
$this->locatorCache->save($this->cache);

Check failure on line 63 in system/Autoloader/FileLocator.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Method CodeIgniter\Cache\FileLocatorCache::save() invoked with 1 parameter, 0 required.
}
}

/**
Expand Down Expand Up @@ -119,6 +152,10 @@ public function locateFile(string $file, ?string $folder = null, string $ext = '
*/
public function getClassname(string $file): string
{
if (isset($this->cache['getClassname'][$file])) {
return $this->cache['getClassname'][$file];
}

$php = file_get_contents($file);
$tokens = token_get_all($php);
$dlm = false;
Expand Down Expand Up @@ -154,7 +191,12 @@ public function getClassname(string $file): string
return '';
}

return $namespace . '\\' . $className;
$fullClassname = $namespace . '\\' . $className;

$this->cache['getClassname'][$file] = $fullClassname;
$this->cacheUpdated = true;

return $fullClassname;
}

/**
Expand All @@ -172,6 +214,10 @@ public function getClassname(string $file): string
*/
public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array
{
if (isset($this->cache['search'][$path])) {
return $this->cache['search'][$path];
}

$path = $this->ensureExt($path, $ext);

$foundPaths = [];
Expand All @@ -197,7 +243,42 @@ public function search(string $path, string $ext = 'php', bool $prioritizeApp =
}

// Remove any duplicates
return array_unique($foundPaths);
$foundPaths = array_unique($foundPaths);

$this->cache['search'][$path] = $foundPaths;
$this->cacheUpdated = true;

return $foundPaths;
}

/**
* Gets cache
*
* @internal For caching only
*/
public function getCache(): array
{
return $this->cache;
}

/**
* Sets cache
*
* @internal For caching only
*/
public function setCache(array $data): void
{
$this->cache = $data;
}

/**
* Is the cache updated?
*
* @internal For caching only
*/
public function isCacheUpdated(): bool
{
return $this->cacheUpdated;
}

/**
Expand All @@ -223,6 +304,10 @@ protected function ensureExt(string $path, string $ext): string
*/
protected function getNamespaces()
{
if (isset($this->cache['getNamespaces'])) {
return $this->cache['getNamespaces'];
}

$namespaces = [];

// Save system for last
Expand All @@ -248,6 +333,9 @@ protected function getNamespaces()

$namespaces[] = $system;

$this->cache['getNamespaces'] = $namespaces;
$this->cacheUpdated = true;

return $namespaces;
}

Expand All @@ -259,6 +347,10 @@ protected function getNamespaces()
*/
public function findQualifiedNameFromPath(string $path)
{
if (isset($this->cache['findQualifiedNameFromPath'][$path])) {
return $this->cache['findQualifiedNameFromPath'][$path];
}

$path = realpath($path) ?: $path;

if (! is_file($path)) {
Expand All @@ -285,6 +377,9 @@ public function findQualifiedNameFromPath(string $path)

// Check if this exists
if (class_exists($className)) {
$this->cache['findQualifiedNameFromPath'][$path] = $className;
$this->cacheUpdated = true;

return $className;
}
}
Expand Down
72 changes: 72 additions & 0 deletions system/Cache/FileLocatorCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Cache;

use CodeIgniter\Autoloader\FileLocator;
use CodeIgniter\Cache\FactoriesCache\FileVarExportHandler;

final class FileLocatorCache
{
/**
* @var CacheInterface|FileVarExportHandler
*/
private $cache;

private FileLocator $locator;

/**
* @param CacheInterface|FileVarExportHandler|null $cache
*/
public function __construct($cache = null)
{
$this->cache = $cache ?? new FileVarExportHandler();
}

public function setLocator(FileLocator $fileLocator)

Check failure on line 34 in system/Cache/FileLocatorCache.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Method CodeIgniter\Cache\FileLocatorCache::setLocator() has no return type specified.
{
$this->locator = $fileLocator;
}

public function save(): void
{
if (! $this->locator->isCacheUpdated()) {
return;
}

$data = $this->locator->getCache();

$this->cache->save($this->getCacheKey(), $data, 3600 * 24);
}

private function getCacheKey(): string
{
return 'FileLocatorCache';
}

public function load(): bool
{
$key = $this->getCacheKey();

if (! $data = $this->cache->get($key)) {
return false;
}

$this->locator->setCache($data);

return true;
}

public function delete(): void
{
$this->cache->delete($this->getCacheKey());
}
}

0 comments on commit f890ccb

Please sign in to comment.