Skip to content

Commit

Permalink
🚀 first release
Browse files Browse the repository at this point in the history
  • Loading branch information
bnomei committed Jul 19, 2024
1 parent ce983e9 commit d0646e2
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 7 deletions.
112 changes: 110 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,111 @@
# kirby-nitro
# ⛽️Kirby Nitro

monkey patches to make kirby faster. use at your own risk.
![Release](https://flat.badgen.net/packagist/v/bnomei/kirby-nitro?color=ae81ff)
![Downloads](https://flat.badgen.net/packagist/dt/bnomei/kirby-nitro?color=272822)
[![Build Status](https://flat.badgen.net/travis/bnomei/kirby-nitro)](https://travis-ci.com/bnomei/kirby-nitro)
[![Maintainability](https://flat.badgen.net/codeclimate/maintainability/bnomei/kirby-nitro)](https://codeclimate.com/github/bnomei/kirby-nitro)
[![Twitter](https://flat.badgen.net/badge/twitter/bnomei?color=66d9ef)](https://twitter.com/bnomei)

Nitro speeds up the loading of content in your Kirby project.

## Commercial Usage

> <br>
> <b>Support open source!</b><br><br>
> This plugin is free but if you use it in a commercial project please consider to sponsor me or make a donation.<br>
> If my work helped you to make some cash it seems fair to me that I might get a little reward as well, right?<br><br>
> Be kind. Share a little. Thanks.<br><br>
> &dash; Bruno<br>
> &nbsp;
| M | O | N | E | Y |
|------------------------------------------------------|---------------------------------------|-------------------------------------------------|-----------------------------------------------------|----------------------------------------------|
| [Github sponsor](https://github.com/sponsors/bnomei) | [Patreon](https://patreon.com/bnomei) | [Buy Me a Coffee](https://buymeacoff.ee/bnomei) | [Paypal dontation](https://www.paypal.me/bnomei/15) | [Hire me](mailto:[email protected]?subject=Kirby) |

## Installation

- unzip [master.zip](https://github.com/bnomei/kirby-nitro/archive/master.zip) as folder `site/plugins/kirby-nitro`
or
- `git submodule add https://github.com/bnomei/kirby-nitro.git site/plugins/kirby-nitro` or
- `composer require bnomei/kirby-nitro`

## Setup

For each template you want to be cached you need to use a model to add the content cache logic using a trait.

**site/models/default.php**

```php
class DefaultPage extends \Kirby\Cms\Page
{
use \Bnomei\ModelWithNitro;
}
```

> [!NOTE]
> You can also use the trait for user models. File models are patched automatically.
## Using the Cache

You can use the single-file-based cache of nitro to store your own key-value pairs, just like with a regular cache in
Kirby. Since the Nitro cache is fully loaded with every request I would not advise to store too many big chunks of
data (like HTML output).

```php
nitro()->cache()->set('mykey', 'value');
nitro()->cache()->set('mykey', 'value', 1);

$value = nitro()->cache()->get('mykey');
$value = nitro()->cache()->getOrSet('mykey', fn() => 'value');
```

## Using the Cache Driver in Kirby

You can also use the singe-file-based cache of Nitro as a **cache driver** for Kirby. This will allow you to use it for
caching of other extensions in Kirby. I would highly recommend to use it for Kirby's UUID cache.

**site/config/config.php**

```php
return [
// ... other options

// use nitro as cache driver for storing uuids
// instead of the default file-based cache
'cache' => [
'uuid' => [
'type' => 'nitro',
],
],

// example: in Lapse plugin
'bnomei.lapse.cache' => [
'type' => 'nitro',
],
];
```

## Settings

| bnomei.nitro. | Default | Description |
|-------------------|-----------------------|------------------------------------------------------------------------------|
| auto-clean-cache | `true` | will clean the cache once before the first get() |
| patch-dir-class | always on | monkey-patch the \Kirby\Filesystem\Dir class to use Nitro for caching |
| patch-files-class | `true` | monkey-patch the \Kirby\CMS\Files class to use Nitro for caching its content |
| max-dirty-cache | `512` | write every N changes or on destruct |
| json-encode-flags | `JSON_THROW_ON_ERROR` | |
| model.read | `true` | read from cache for all models that use the ModelWithNitro trait |
| model.write | `true` | write to cache for all models that use the ModelWithNitro trait |

## Disclaimer

This plugin is provided "as is" with no guarantee. Use it at your own risk and always test it yourself before using it
in a production environment. If you find any issues,
please [create a new issue](https://github.com/bnomei/kirby-nitro/issues/new).

## License

[MIT](https://opensource.org/licenses/MIT)

It is discouraged to use this plugin in any project that promotes racism, sexism, homophobia, animal abuse, violence or
any other form of hate speech.
1 change: 1 addition & 0 deletions classes/Nitro.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public function __construct(array $options = [])
'enabled' => true,
'cacheDir' => realpath(__DIR__.'/../').'/cache',
'cacheType' => 'json',
'json-encode-flags' => JSON_THROW_ON_ERROR,
], $options);

foreach ($this->options as $key => $value) {
Expand Down
3 changes: 2 additions & 1 deletion classes/Nitro/DirInventory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class DirInventory

public function __construct(array $options = [])
{
// can not use option() as it might run before Kirby is loaded
$this->options = $options;
$this->isDirty = false;
$this->data = [];
Expand All @@ -39,7 +40,7 @@ public function __destruct()
opcache_invalidate($file);
}
} else {
F::write($file, json_encode($this->data));
F::write($file, json_encode($this->data, $this->options['json-encode-flags']));
}
}

Expand Down
42 changes: 40 additions & 2 deletions classes/Nitro/SingleFileCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function __construct(array $options = [])

$this->options = array_merge([
'auto-clean-cache' => option('bnomei.nitro.auto-clean-cache'),
'json-encode-flags' => option('bnomei.nitro.json-encode-flags'),
'max-dirty-cache' => (int) option('bnomei.nitro.max-dirty-cache'),
'debug' => option('debug'),
], $options);
Expand Down Expand Up @@ -56,6 +57,14 @@ public function set(string $key, $value, int $minutes = 0): bool
*/

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

// flatten kirby fields
$value = $this->serialize($value);

// make sure the value can be stored as json
// if not fail here so a trace is more helpful
$value = json_decode(json_encode($value, $this->options['json-encode-flags']), true);

$this->data[$key] = (new Value($value, $minutes))->toArray();
$this->isDirty++;
if ($this->isDirty > $this->options['max-dirty-cache']) {
Expand Down Expand Up @@ -142,14 +151,43 @@ private function file()
return kirby()->cache('bnomei.nitro.sfc')->root().'/single-file-cache.json';
}

private function write(): bool
public function write(): bool
{
if ($this->isDirty === 0) {
return false;
}
F::write($this->file(), json_encode($this->data));
F::write($this->file(), json_encode($this->data, $this->options['json-encode-flags']));
$this->isDirty = 0;

return true;
}

private static function isCallable($value): bool
{
// do not call global helpers just methods or closures
return ! is_string($value) && is_callable($value);
}

public function serialize($value)
{
if (! $value) {
return null;
}
$value = self::isCallable($value) ? $value() : $value;

if (is_array($value)) {
$items = [];
foreach ($value as $key => $item) {
$items[$key] = $this->serialize($item);
}

return $items;
}

if (is_a($value, 'Kirby\Content\Field')) {
return $value->value();
}

return $value;
}
}
7 changes: 6 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "bnomei/kirby-nitro",
"type": "kirby-plugin",
"version": "1.0.0",
"description": "",
"description": "Nitro speeds up the loading of content in your Kirby project.",
"license": "MIT",
"authors": [
{
Expand Down Expand Up @@ -69,5 +69,10 @@
},
"conflict": {
"bnomei/kirby3-boost": "*"
},
"suggest": {
"bnomei/kirby-blueprints": "PHP Class-based Blueprints for Kirby CMS for better type safety and code completion.",
"bnomei/kirby3-lapse": "Cache any data until set expiration time (with automatic keys).",
"getkirby/staticache": "Static site performance on demand!"
}
}
27 changes: 26 additions & 1 deletion index.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function nitro(): \Bnomei\Nitro
'patch-files-class' => true,
'auto-clean-cache' => true,
'max-dirty-cache' => 512, // write every N changes or on destruct
'json-encode-flags' => JSON_THROW_ON_ERROR, // | JSON_INVALID_UTF8_IGNORE,
'model' => [
'read' => true,
'write' => true,
Expand All @@ -32,8 +33,32 @@ function nitro(): \Bnomei\Nitro
},
'page.*:after' => function ($event, $page) {
if ($event->action() !== 'render') {
\Bnomei\Nitro::singleton()->flush();
\Bnomei\Nitro::singleton()->dir()->flush();
}
},
],
'commands' => [
'nitro:index' => [
'description' => 'Run Nitro Index',
'args' => [],
'command' => static function ($cli): void {

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

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

$cli->success('Done.');

if (function_exists('janitor')) {
janitor()->data([
'status' => 200,
'message' => $count.' models indexed.',
]);
}
},
],
],
]);
20 changes: 20 additions & 0 deletions tests/NitroTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@
expect($value)->toBe('value');
});

it('will serialize kirby\content\fields to their value', function () {
$cache = nitro()->cache();
$cache->set('home.title', page('home')->title());
$value = $cache->get('home.title');

expect($value)->toBe('Home');
});

it('will serialize objects if they support it', function () {
$cache = nitro()->cache();
$cache->set('object', new \Kirby\Toolkit\Obj([
'hello' => 'world',
]));
$value = $cache->get('object');

expect($value)->toBe([
'hello' => 'world',
]);
});

it('will not use the cache in debug mode', function () {
Nitro::$singleton = null;

Expand Down

0 comments on commit d0646e2

Please sign in to comment.