Skip to content

Commit

Permalink
🎉 initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bnomei committed Jun 29, 2024
1 parent 03e1f2e commit ff4a21a
Show file tree
Hide file tree
Showing 19 changed files with 9,017 additions and 2 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2
15 changes: 15 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Auto detect text files and perform LF normalization
* text=auto

/*-lock.json export-ignore
/.* export-ignore
/docker-compose.yml export-ignore
/docs export-ignore
/examples export-ignore
/package.json export-ignore
/phpstan.neon.dist export-ignore
/phpunit.xml export-ignore
/ray.php export-ignore
/pint.json export-ignore
/tests export-ignore
/collections/example_*.php export-ignore
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# These are supported funding model platforms

github: bnomei # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: bnomei # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://buymeacoff.ee/bnomei', 'https://paypal.me/bnomei']
24 changes: 24 additions & 0 deletions .github/workflows/fix-php-code-style-issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Fix PHP code style issues

on:
push:
paths:
- '**.php'

jobs:
php-code-styling:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

- name: Fix PHP code style issues
uses: aglipanci/laravel-pint-action@2.3.0

- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Fix styling
27 changes: 27 additions & 0 deletions .github/workflows/pest-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Pest Tests

on: ['push', 'pull_request']

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
tools: composer:v2
coverage: xdebug

- name: Install
run: composer install --no-interaction --prefer-dist --optimize-autoloader

- name: Run Tests
run: |
php tests/patch.php
./vendor/bin/pest --group=SetupPagesInSeparatePHPUnitRun
./vendor/bin/pest
29 changes: 29 additions & 0 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: PHPStan

on:
push:
paths:
- '**.php'
- 'phpstan.neon.dist'

jobs:
phpstan:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
tools: composer:v2
coverage: none

- name: Install
run: |
composer install --no-interaction --prefer-dist --optimize-autoloader
- name: Run PHPStan
run: ./vendor/bin/phpstan --error-format=github
39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# OS files
.DS_Store
.idea
*.cache

/build

/tests/kirby
/tests/logs
/tests/media
!/tests/content/*
/tests/site/accounts
/tests/site/cache
/tests/site/sessions
/tests/site/plugins/kirby3-sqlite-cachedriver
/tests/site/plugins/kirby3-redis-cachedriver
/tests/site/plugins/kql

# files of Composer dependencies that are not needed for the plugin
/vendor/**/.*
/vendor/**/*.json
/vendor/**/*.txt
/vendor/**/*.md
/vendor/**/*.yml
/vendor/**/*.yaml
/vendor/**/*.xml
/vendor/**/*.dist
/vendor/**/readme.php
/vendor/**/LICENSE
/vendor/**/COPYING
/vendor/**/VERSION
/vendor/**/docs/*
/vendor/**/example/*
/vendor/**/examples/*
/vendor/**/test/*
/vendor/**/tests/*
/vendor/**/php4/*
/vendor/getkirby/composer-installer
coverage.xml
96 changes: 94 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,94 @@
# Khulan - Kirby MongoDB
Cache Driver and Content Cache using MongoDB
# 🐎 Khulan - Kirby MongoDB

![Release](https://flat.badgen.net/packagist/v/bnomei/kirby-mongodb?color=ae81ff)
![Downloads](https://flat.badgen.net/packagist/dt/bnomei/kirby-mongodb?color=272822)
[![Build Status](https://flat.badgen.net/travis/bnomei/kirby-mongodb)](https://travis-ci.com/bnomei/kirby-mongodb)
[![Maintainability](https://flat.badgen.net/codeclimate/maintainability/bnomei/kirby-mongodb)](https://codeclimate.com/github/bnomei/kirby-mongodb)
[![Twitter](https://flat.badgen.net/badge/twitter/bnomei?color=66d9ef)](https://twitter.com/bnomei)

Khulan is a cache driver and content cache for Kirby using MongoDB.

## 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:b@bnomei.com?subject=Kirby) |

## Installation

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

## Usecase

The plugin caches all content files and keeps the cache up to date when you add/remove or update content. This cache
will be used when constructing page/file/user objects making everything that involves model faster (even the
Panel).

## 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\Khulan;
}
```

> Note: You can also use the trait for user models. File models are patched automatically.
## Accessing the Cache

```php
/** @var \Kirby\Cache\Cache $cache */
$cache = \Bnomei\Mongodb::singleton();

$cache->set('mykey', 'myvalue', 5); // ttl in minutes
$value = $cache->get('mykey');
```

## Accessing the MongoDB Client

```php
/** @var \MongoDB\Client $client */
$client = \Bnomei\Mongodb::singleton()->client();

$client->listDatabases();
```

## Settings

| bnomei.mongodb. | Default | Description |
|--------------------------|-------------|------------------------------------------------------------------------------|
| host | `127.0.0.1` | |
| port | `27017` | |
| khulan.read | `true` | read from cache |
| khulan.write | `true` | write to cache |
| khulan.patch-files-class | `true` | monkey-patch the \Kirby\CMS\Files class to use Khulan for caching it content |

## 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-mongodb/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.

130 changes: 130 additions & 0 deletions classes/Khulan.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

declare(strict_types=1);

namespace Bnomei;

use Kirby\Filesystem\F;
use Kirby\Toolkit\Str;

trait Khulan
{
/** @var bool */
private bool $khulanCacheWillBeDeleted;

public function hasKhulan(): bool
{
return true;
}

public function setBoostWillBeDeleted(bool $value): void
{
$this->khulanCacheWillBeDeleted = $value;
}

public function keyKhulan(?string $languageCode = null): string
{
$key = hash('xxh3', $this->id()); // can not use UUID since content not loaded yet
if (! $languageCode) {
$languageCode = kirby()->languages()->count() ? kirby()->language()->code() : null;
}
if ($languageCode) {
$key = $key.'-'.$languageCode;
}

return $key;
}

public function readContentCache(?string $languageCode = null): ?array
{
// TODO: change to direct client findByID
return Mongodb::singleton()->get(
$this->keyKhulan($languageCode).'-content',
null
);
}

public function readContent(?string $languageCode = null): array
{
// read from boostedCache if exists
$data = option('bnomei.mongodb.khulan.read') === false || option('debug') ? null : $this->readContentCache($languageCode);

// read from file and update boostedCache
if (! $data) {
$data = parent::readContent($languageCode);
if ($data && $this->khulanCacheWillBeDeleted !== true) {
$this->writeKhulan($data, $languageCode);
}
}

return $data;
}

public function writeKhulan(?array $data = null, ?string $languageCode = null): bool
{
$cache = Mongodb::singleton();
if (! $cache || option('bnomei.mongodb.khulan.write') === false) {
return true;
}

$modified = $this->modified();

// in rare case file does not exists or is not readable
if ($modified === false) {
$this->deleteKhulan(); // whatever was in the cache is no longer valid

return false; // try again another time
}

// TODO: change to direct client insertOne
return $cache->set(
$this->keyKhulan($languageCode).'-content',
array_filter($data, fn ($content) => $content !== null),
option('bnomei.mongodb.expire')
);
}

public function writeContent(array $data, ?string $languageCode = null): bool
{
// write to file and cache
return parent::writeContent($data, $languageCode) &&
$this->writeKhulan($data, $languageCode);
}

public function deleteKhulan(): bool
{
$cache = Mongodb::singleton();
if (! $cache) {
return true;
}

$this->setBoostWillBeDeleted(true);

foreach (kirby()->languages() as $language) {
// TODO: change to direct client deleteByID
$cache->remove(
$this->keyKhulan($language->code()).'-content'
);
}

// TODO: change to direct client deleteByID
$cache->remove(
$this->keyKhulan().'-content'
);

return true;
}

public function delete(bool $force = false): bool
{
$cache = Mongodb::singleton();
if (! $cache) {
return parent::delete($force);
}

$success = parent::delete($force);
$this->deleteKhulan();

return $success;
}
}
Loading

0 comments on commit ff4a21a

Please sign in to comment.