classes/ModelHasBoost.php
<?php
declare(strict_types=1);
namespace Bnomei;
trait ModelHasBoost
{
/** @var bool */
private $boostWillBeDeleted;
public function hasBoost(): bool
{
return true;
}
public function checkModifiedTimestampForContentBoost(): bool
{
return option('bnomei.boost.fileModifiedCheck');
}
public function setBoostWillBeDeleted(bool $value): void
{
$this->boostWillBeDeleted = $value;
}
public function isContentBoosted(?string $languageCode = null): bool
{
return $this->readContentCache($languageCode) !== null;
}
public function contentBoostedKey(?string $languageCode = null): string
{
$key = hash(BoostCache::hashalgo(), $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 isContentCacheExpiredByModified(?string $languageCode = null): bool
{
$cache = BoostCache::singleton();
if (! $cache) {
return true;
}
$modifiedCache = $cache->get(
$this->contentBoostedKey($languageCode).'-modified',
null
);
if (! $modifiedCache) {
return true;
}
$modified = $this->modified();
// in rare case the file does not exist or is not readable
if ($modified === false) {
return true;
}
// otherwise compare
if ($modifiedCache && intval($modifiedCache) < intval($modified)) {
return true;
}
return false;
}
public function readContentCache(?string $languageCode = null): ?array
{
if ($this->checkModifiedTimestampForContentBoost()) {
if ($this->isContentCacheExpiredByModified($languageCode)) {
return null;
}
}
return BoostCache::singleton()->get(
$this->contentBoostedKey($languageCode).'-content',
null
);
}
public function readContent(?string $languageCode = null): array
{
// read from boostedCache if exists
$data = option('bnomei.boost.read') === false || option('debug') ? null : $this->readContentCache($languageCode);
// read from file and update boostedCache
if (! $data) {
$data = parent::readContent($languageCode);
if ($data && $this->boostWillBeDeleted !== true) {
$this->writeContentCache($data, $languageCode);
}
}
return $data;
}
public function writeContentCache(?array $data = null, ?string $languageCode = null): bool
{
$cache = BoostCache::singleton();
if (! $cache || option('bnomei.boost.write') === false) {
return true;
}
$modified = $this->modified();
// in rare case file does not exists or is not readable
if ($modified === false) {
$this->deleteContentCache(); // whatever was in the cache is no longer valid
return false; // try again another time
}
$cache->set(
$this->contentBoostedKey($languageCode).'-modified',
$modified,
option('bnomei.boost.expire')
);
return $cache->set(
$this->contentBoostedKey($languageCode).'-content',
array_filter($data, fn ($content) => $content !== null),
option('bnomei.boost.expire')
);
}
public function writeContent(array $data, ?string $languageCode = null): bool
{
// write to file and cache
return parent::writeContent($data, $languageCode) &&
$this->writeContentCache($data, $languageCode);
}
public function deleteContentCache(): bool
{
$cache = BoostCache::singleton();
if (! $cache) {
return true;
}
$this->setBoostWillBeDeleted(true);
foreach (kirby()->languages() as $language) {
$cache->remove(
$this->contentBoostedKey($language->code()).'-content'
);
$cache->remove(
$this->contentBoostedKey($language->code()).'-modified'
);
}
$cache->remove(
$this->contentBoostedKey().'-content'
);
$cache->remove(
$this->contentBoostedKey().'-modified'
);
return true;
}
public function delete(bool $force = false): bool
{
$cache = BoostCache::singleton();
if (! $cache) {
return parent::delete($force);
}
$success = parent::delete($force);
$this->deleteContentCache();
return $success;
}
}