-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8017 from kenjis/feat-FileLocator-Caching
feat: FileLocator caching
- Loading branch information
Showing
15 changed files
with
455 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
<?php | ||
|
||
/** | ||
* This file is part of CodeIgniter 4 framework. | ||
* | ||
* (c) CodeIgniter Foundation <[email protected]> | ||
* | ||
* 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 | ||
* | ||
* @see \CodeIgniter\Autoloader\FileLocatorCachedTest | ||
*/ | ||
final class FileLocatorCached implements FileLocatorInterface | ||
{ | ||
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) | ||
{ | ||
$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); | ||
} | ||
} | ||
|
||
/** | ||
* Delete cache data | ||
*/ | ||
public function deleteCache(): void | ||
{ | ||
$this->cacheHandler->delete($this->cacheKey); | ||
} | ||
|
||
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'): false|string | ||
{ | ||
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
/** | ||
* This file is part of CodeIgniter 4 framework. | ||
* | ||
* (c) CodeIgniter Foundation <[email protected]> | ||
* | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
namespace CodeIgniter\Autoloader; | ||
|
||
/** | ||
* Allows loading non-class files in a namespaced manner. | ||
* Works with Helpers, Views, etc. | ||
*/ | ||
interface FileLocatorInterface | ||
{ | ||
/** | ||
* Attempts to locate a file by examining the name for a namespace | ||
* and looking through the PSR-4 namespaced files that we know about. | ||
* | ||
* @param string $file The relative file path or namespaced file to | ||
* locate. If not namespaced, search in the app | ||
* folder. | ||
* @param string|null $folder The folder within the namespace that we should | ||
* look for the file. If $file does not contain | ||
* this value, it will be appended to the namespace | ||
* folder. | ||
* @param string $ext The file extension the file should have. | ||
* | ||
* @return false|string The path to the file, or false if not found. | ||
*/ | ||
public function locateFile(string $file, ?string $folder = null, string $ext = 'php'); | ||
|
||
/** | ||
* Examines a file and returns the fully qualified class name. | ||
*/ | ||
public function getClassname(string $file): string; | ||
|
||
/** | ||
* Searches through all of the defined namespaces looking for a file. | ||
* Returns an array of all found locations for the defined file. | ||
* | ||
* Example: | ||
* | ||
* $locator->search('Config/Routes.php'); | ||
* // Assuming PSR4 namespaces include foo and bar, might return: | ||
* [ | ||
* 'app/Modules/foo/Config/Routes.php', | ||
* 'app/Modules/bar/Config/Routes.php', | ||
* ] | ||
*/ | ||
public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array; | ||
|
||
/** | ||
* Find the qualified name of a file according to | ||
* the namespace of the first matched namespace path. | ||
* | ||
* @return false|string The qualified name or false if the path is not found | ||
*/ | ||
public function findQualifiedNameFromPath(string $path); | ||
|
||
/** | ||
* Scans the defined namespaces, returning a list of all files | ||
* that are contained within the subpath specified by $path. | ||
* | ||
* @return string[] List of file paths | ||
*/ | ||
public function listFiles(string $path): array; | ||
|
||
/** | ||
* Scans the provided namespace, returning a list of all files | ||
* that are contained within the sub path specified by $path. | ||
* | ||
* @return string[] List of file paths | ||
*/ | ||
public function listNamespaceFiles(string $prefix, string $path): array; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.