Skip to content

Commit

Permalink
✨ indexing users, datetime objects
Browse files Browse the repository at this point in the history
  • Loading branch information
bnomei committed Jul 6, 2024
1 parent 640b48d commit 939de64
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 28 deletions.
19 changes: 18 additions & 1 deletion classes/Khulan.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,24 @@ public static function index(int $iterations = 2): array
}
$count++;
}
// TODO: files, users

/** @var File $file */
foreach (kirby()->users() as $user) {
if ($user->hasKhulan() !== true) {
continue;
}
if (kirby()->multilang()) {
foreach (kirby()->languages() as $language) {
$content = $user->content($language->code())->toArray();
$hash[] = $user->email();
$user->writeKhulan($content, $language->code());
}
} else {
$hash[] = $user->email();
$user->writeKhulan($user->content()->toArray());
}
$count++;
}

$meta = [
'count' => $count,
Expand Down
81 changes: 63 additions & 18 deletions classes/ModelWithKhulan.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

namespace Bnomei;

use DateTime;
use Exception;
use Kirby\Cms\File;
use Kirby\Cms\Page;
use Kirby\Cms\Site;
use Kirby\Cms\User;
use Kirby\Data\Yaml;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Str;
use MongoDB\BSON\ObjectId;
use MongoDB\BSON\UTCDateTime;

trait ModelWithKhulan
{
Expand All @@ -35,7 +40,8 @@ public function keyKhulan(?string $languageCode = null): string
$key = $key.'-'.$languageCode;
}

return hash('xxh3', $key);
// mongodb _id must be 24 chars long
return substr(hash('md5', $key), 0, 24);
}

public function readContentCache(?string $languageCode = null): ?array
Expand Down Expand Up @@ -73,7 +79,17 @@ public function writeKhulan(?array $data = null, ?string $languageCode = null):
return true;
}

$modified = $this->modified();
$modified = null;
if ($this instanceof Site) {
// site()->modified() does crawl index but not return change of its content file
$siteFile = site()->storage()->read(
site()->storage()->defaultVersion(),
kirby()->defaultLanguage()->code()
)[0];
$modified = $modified.filemtime($siteFile);
} else {
$modified = $this->modified();
}

// in rare case file does not exists or is not readable
if ($modified === false) {
Expand All @@ -95,12 +111,19 @@ public function writeKhulan(?array $data = null, ?string $languageCode = null):
$meta = [
'id' => $this->id() ?? null,
'modified' => $modified,
'modified{}' => new UTCDateTime($modified * 1000),
'slug' => $this->id() ? array_pop($slug) : null,
'template' => $this->intendedTemplate()->name(),
'class' => $this::class,
'language' => $languageCode,
'modelType' => $modelType,
];
if ($this instanceof Page) {
$meta['template'] = $this->intendedTemplate()->name();
} elseif ($this instanceof File) {
$meta['filename'] = $this->filename();
} elseif ($this instanceof User) {
$meta['email'] = $this->email();
}
$data = $this->encodeKhulan($data, $languageCode) + $meta;

// _id is not allowed as data key
Expand All @@ -109,7 +132,7 @@ public function writeKhulan(?array $data = null, ?string $languageCode = null):
}

$status = khulan()->findOneAndUpdate(
['_id' => $this->keyKhulan($languageCode)],
['_id' => new ObjectId($this->keyKhulan($languageCode))],
['$set' => $data],
['upsert' => true]
);
Expand Down Expand Up @@ -168,11 +191,23 @@ public function encodeKhulan(array $data, ?string $languageCode = null): array
if (preg_match('/^[\w\s-]+(,\s*[\w\s-]+)*$/', $value) && in_array(
$type, ['tags', 'select', 'multiselect', 'radio', 'checkbox']
)) {
$copy[$key.'[,]'] = explode(',', $value);
$tags = explode(',', $value);
$tags = array_map('trim', $tags);
$tags = array_filter($tags, function ($value) {
return ! empty($value);
});
$copy[$key.'[,]'] = $tags;

continue; // process next key value pair
}

if (in_array(
$type, ['date']
)) {
// convert iso date to mongodb date
$copy[$key.'{}'] = new UTCDateTime((new DateTime($value))->getTimestamp() * 1000);
}

// if it is a valid yaml string, convert it to an array
if (in_array(
$type, ['pages', 'files', 'users']
Expand Down Expand Up @@ -218,8 +253,9 @@ public function encodeKhulan(array $data, ?string $languageCode = null): array
}
}
}
} catch (\Exception $e) {
} catch (Exception $e) {
// do nothing
// ray($e->getMessage());
}
}
// if it is a valid yaml string, convert it to an array
Expand All @@ -231,7 +267,7 @@ public function encodeKhulan(array $data, ?string $languageCode = null): array
if (is_array($v)) {
$copy[$key.'[]'] = $v;
}
} catch (\Exception $e) {
} catch (Exception $e) {
// do nothing
}
}
Expand All @@ -253,13 +289,13 @@ public function decodeKhulan(?array $data = []): array
$data = json_decode(json_encode($data), true);

$copy = $data;
foreach ($data as $key => $value) {
if (is_array($value) && Str::endsWith($key, '[,]')) {
unset($copy[$key]);
} elseif (is_array($value) && Str::endsWith($key, '[]')) {
unset($copy[$key]);
}
}

// remove any empty values
$copy = array_filter($copy, function ($value) {
return ! empty($value);
});

// remove meta
$meta = [
'id',
'modified',
Expand All @@ -268,17 +304,26 @@ public function decodeKhulan(?array $data = []): array
'class',
'language',
'modelType',
'filename',
'email',
];
foreach ($meta as $key) {
if (array_key_exists($key, $copy)) {
unset($copy[$key]);
}
}

// remove any empty values
$copy = array_filter($copy, function ($value) {
return ! empty($value);
});
// remove dynamic keys
foreach ($data as $key => $value) {
if (is_array($value) && (
Str::endsWith($key, '[,]') ||
Str::endsWith($key, '[]') ||
Str::endsWith($key, '{}')
)
) {
unset($copy[$key]);
}
}

return $copy;
}
Expand Down
3 changes: 2 additions & 1 deletion index.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function khulan(string|array|null $search = null): mixed
['_id' => $search],
['id' => $search],
['uuid' => $search],
['email' => $search], // user
],
]));
}
Expand Down Expand Up @@ -80,7 +81,7 @@ function khulan(string|array|null $search = null): mixed
'hooks' => [
'system.loadPlugins:after' => function () {
if ((option('bnomei.mongodb.khulan.read') ||
option('bnomei.mongodb.khulan.write') ) &&
option('bnomei.mongodb.khulan.write')) &&
khulan()->countDocuments() === 0) {
Khulan::index();
}
Expand Down
16 changes: 16 additions & 0 deletions tests/MongodbTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use Bnomei\Khulan;
use Bnomei\Mongodb;
use Kirby\Cms\Page;
use Kirby\Cms\User;
use Kirby\Cms\Users;
use MongoDB\BSON\ObjectId;
use MongoDB\Collection;
use MongoDB\Model\BSONDocument;
Expand Down Expand Up @@ -169,6 +171,20 @@
expect($pages->count())->toBe(1);
});

it('can find a user by email', function () {
Khulan::index();

$email = kirby()->users()->first()->email();

$users = khulan(['email' => $email]);
expect($users)->toBeInstanceOf(Users::class)
->and($users->first()->email())->toBe($email);

$user = khulan($email);
expect($user)->toBeInstanceOf(User::class)
->and($user->email())->toBe($email);
});

it('can run the benchmark', function () {
mongo()->benchmark();
})->skip();
8 changes: 6 additions & 2 deletions tests/content/2_betterharder/default.en.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ Text-non-translated: non

----

Date: 2024-07-06 18:15:00

----

Tags: Daft, Punk

----

Category:
Category:

----

Related: - page://fasterstronger

----

Uuid: betterharder
Uuid: betterharder
3 changes: 3 additions & 0 deletions tests/site/blueprints/tabs/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ sections:
type: text
translate: false
width: 1/2
date:
type: date
time: true
tags:
type: tags
category:
Expand Down
11 changes: 5 additions & 6 deletions tests/site/plugins/khulanuser/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ public function hello(): string
}
}

// TODO
//Kirby::plugin('myplugin/user', [
// 'userModels' => [
// 'admin' => AdminUser::class, // admin is default role
// ],
//]);
Kirby::plugin('myplugin/user', [
'userModels' => [
'admin' => AdminUser::class, // admin is default role
],
]);

0 comments on commit 939de64

Please sign in to comment.