Skip to content

Commit

Permalink
♻️ better tests and fixed a few edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
bnomei committed Jul 21, 2024
1 parent 064da5d commit a553c71
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 82 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ArticlePage extends \Kirby\Cms\Page
{
use \Bnomei\ModelWithNitro;
}
``
```

> [!NOTE]
> You can also use the trait for user models. File models are patched automatically.
Expand Down
40 changes: 26 additions & 14 deletions classes/Nitro.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

use Bnomei\Nitro\DirInventory;
use Bnomei\Nitro\SingleFileCache;
use Closure;
use Kirby\Cache\FileCache;
use Kirby\Cms\App;
use Kirby\Cms\Files;
use Kirby\Filesystem\Dir;
use Kirby\Filesystem\F;
use Kirby\Toolkit\Str;
Expand All @@ -18,17 +21,20 @@ class Nitro

private ?SingleFileCache $singleFileCache = null;

/**
* @var true
*/
private bool $_ready = false;

Check failure on line 27 in classes/Nitro.php

View workflow job for this annotation

GitHub Actions / phpstan

Property Bnomei\Nitro::$_ready (true) does not accept default value of type false.

public function __construct(array $options = [])
{
$this->options = array_merge([
'enabled' => true,
'cacheDir' => realpath(__DIR__.'/../').'/cache',
'cacheType' => 'json',
'json-encode-flags' => JSON_THROW_ON_ERROR,
], $options);

foreach ($this->options as $key => $value) {
if ($value instanceof \Closure) {
if ($value instanceof Closure) {
$this->options[$key] = $value();
}
}
Expand Down Expand Up @@ -66,19 +72,22 @@ public function ready(): void
$this->replaceCacheFolderWithSymlink();
$this->patchFilesClass();
$this->dir()->patchDirClass();

$this->_ready = true;
}

public function isReady(): bool
{
return $this->_ready;
}

/*
* map the current kirby cache plugin folder (depending on $_HOST) to the cache folder inside the plugin itself.
*/
private function replaceCacheFolderWithSymlink(): bool
{
if (! $this->options['enabled']) {
return false;
}

$internalDir = $this->options['cacheDir'];
/** @var \Kirby\Cache\FileCache $cache */
/** @var FileCache $cache */
$cache = kirby()->cache('bnomei.nitro.dir');
$kirbyDir = $cache->root();

Expand All @@ -97,30 +106,33 @@ private function replaceCacheFolderWithSymlink(): bool
return true;
}

private function patchFilesClass(): void
public function patchFilesClass(): bool
{
if (option('bnomei.nitro.patch-files-class') !== true) {
return;
return false;
}

$patch = $this->options['cacheDir'].'/files.'.App::versionHash().'.patch';
if (file_exists($patch)) {
return;
return false;
}

$filesClass = (new ReflectionClass(\Kirby\Cms\Files::class))->getFileName();
$filesClass = (new ReflectionClass(Files::class))->getFileName();
if ($filesClass && F::exists($filesClass) && F::isWritable($filesClass)) {
$code = F::read($filesClass);
if ($code && Str::contains($code, '\Bnomei\NitroFile::factory') === false) {
$code = str_replace('File::factory(', '\Bnomei\NitroFile::factory(', $code);
F::write($filesClass, $code);

if (function_exists('opcache_invalidate')) {
opcache_invalidate($filesClass);
opcache_invalidate($filesClass); // @codeCoverageIgnore
}
}
F::write($patch, date('c'));

return F::write($patch, date('c'));
}

return false;
}

public function modelIndex(): int
Expand Down
2 changes: 1 addition & 1 deletion classes/Nitro/AbortCachingExeption.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class AbortCachingExeption extends \Exception
{
public function __construct($message = 'Abort Caching', $code = 0, ?\Throwable $previous = null)
public function __construct(string $message = 'Abort Caching', int $code = 0, ?\Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
Expand Down
82 changes: 25 additions & 57 deletions classes/Nitro/DirInventory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DirInventory

private bool $isDirty;

private array $options = [];
private array $options;

public function __construct(array $options = [])
{
Expand All @@ -28,65 +28,36 @@ public function __construct(array $options = [])

public function __destruct()
{
if (! $this->isDirty || ! $this->enabled()) {
return;
}

$file = $this->file();

if ($this->cacheType() === 'php') {
F::write($file, '<?php'.PHP_EOL.' return '.var_export($this->data, true).';');
if (function_exists('opcache_invalidate')) {
opcache_invalidate($file);
}
} else {
F::write($file, json_encode($this->data, $this->options['json-encode-flags']));
}
$this->write();
}

public function file(): string
{
if ($this->cacheType() === 'php') {
return $this->cacheDir().'/dir-inventory.php';
}

return $this->cacheDir().'/dir-inventory.json';
}

private function load(): void
{
if (! $this->enabled() || ! file_exists($this->file())) {
if (! file_exists($this->file())) {
return;
}

if ($this->cacheType() === 'php') {
$this->data = include $this->file();
} else {
$data = file_get_contents($this->file());
$data = $data ? json_decode($data, true) : [];
if (is_array($data) || is_null($data)) {
$this->data = $data;
}
$data = file_get_contents($this->file());
$data = $data ? json_decode($data, true) : [];
if (is_array($data) || is_null($data)) {
$this->data = $data;
}
}

public function get(string|array $key): ?array
{
if (! $this->enabled()) {
return null;
}

$key = $this->key($key);

return A::get($this->data, $key);
}

public function set(string|array $key, ?array $input = null): void
{
if (! $this->enabled()) {
return;
}

$this->isDirty = true;
$key = $this->key($key);
$this->data[$key] = $input;
Expand All @@ -108,31 +79,16 @@ private function key(string|array $key): string
return is_array($key) ? hash('xxh3', print_r($key, true)) : $key;
}

private function enabled(): bool
{
return $this->options['enabled'];
}

private function cacheDir(): string
public function cacheDir(): string
{
return $this->options['cacheDir'];
}

private function cacheType(): string
public function patchDirClass(): bool
{
return $this->options['cacheType'];
}

public function patchDirClass(): void
{

if (! $this->enabled()) {
return;
}

$patch = $this->cacheDir().'/dir-inventory.'.App::versionHash().'.patch';
if (file_exists($patch)) {
return;
return false;
}

$reflection = new ReflectionClass(Dir::class);
Expand All @@ -141,7 +97,7 @@ public function patchDirClass(): void
$content = $file ? file_get_contents($file) : null;

if (! $file || ! $content) {
return;
return false;
}

$head = <<<'CODE'
Expand Down Expand Up @@ -171,10 +127,22 @@ public function patchDirClass(): void
F::write($file, $content);

if (function_exists('opcache_invalidate')) {
opcache_invalidate($file);
opcache_invalidate($file); // @codeCoverageIgnore
}
}

F::write($patch, date('c'));
return F::write($patch, date('c'));
}

public function write(): bool
{
if (! $this->isDirty) {
return false;
}

$file = $this->file();
$this->isDirty = false;

return F::write($file, json_encode($this->data, $this->options['json-encode-flags']));
}
}
20 changes: 14 additions & 6 deletions classes/Nitro/SingleFileCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function set(string|array $key, mixed $value, int $minutes = 0): bool

$this->data[$key] = (new Value($value, $minutes))->toArray();
$this->isDirty++;
if ($this->isDirty > $this->options['max-dirty-cache']) {
if ($this->isDirty >= $this->options['max-dirty-cache']) {
$this->write();
}

Expand All @@ -90,7 +90,7 @@ public function set(string|array $key, mixed $value, int $minutes = 0): bool
/**
* {@inheritDoc}
*/
public function retrieve(string|array $key): ?Value
public function retrieve(string $key): ?Value
{
$value = A::get($this->data, $this->key($key));

Expand All @@ -101,12 +101,16 @@ public function retrieve(string|array $key): ?Value
return is_array($value) ? Value::fromArray($value) : $value;
}

public function get(string $key, mixed $default = null): mixed
public function get(array|string $key, mixed $default = null): mixed
{
if ($this->options['debug']) {
return $default;
}

if (is_array($key)) {
$key = print_r($key, true);
}

return parent::get($key, $default);
}

Expand All @@ -119,7 +123,7 @@ public function remove(string|array $key): bool
if (array_key_exists($key, $this->data)) {
unset($this->data[$key]);
$this->isDirty++;
if ($this->isDirty > $this->options['max-dirty-cache']) {
if ($this->isDirty >= $this->options['max-dirty-cache']) {
$this->write();
}
}
Expand Down Expand Up @@ -161,10 +165,9 @@ public function write(): bool
if ($this->isDirty === 0) {
return false;
}
F::write($this->file(), json_encode($this->data, $this->options['json-encode-flags']));
$this->isDirty = 0;

return true;
return F::write($this->file(), json_encode($this->data, $this->options['json-encode-flags']));
}

private static function isCallable(mixed $value): bool
Expand Down Expand Up @@ -195,4 +198,9 @@ public function serialize(mixed $value): mixed

return $value;
}

public function count(): int
{
return count($this->data);
}
}
3 changes: 0 additions & 3 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ function nitro(): \Bnomei\Nitro
'args' => [],
'command' => static function ($cli): void {

$kirby = $cli->kirby();
$kirby->impersonate('kirby');

$cli->out('Indexing...');
$count = nitro()->modelIndex();
$cli->out($count.' models indexed.');
Expand Down
Loading

0 comments on commit a553c71

Please sign in to comment.