2024-04-17 11:41:10 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Classes;
|
|
|
|
|
|
|
|
use Illuminate\Filesystem\FilesystemAdapter;
|
2024-04-18 00:24:45 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Class MetadataManager
|
|
|
|
*
|
|
|
|
* This class is designed to handle metadata for articles or any other items that
|
|
|
|
* might have associated metadata stored in a JSON format. It uses Laravel's
|
|
|
|
* Collections for flexible data manipulation and the disk for storage.
|
|
|
|
*/
|
|
|
|
class MetadataManager
|
2024-04-17 11:41:10 +02:00
|
|
|
{
|
2024-04-18 00:24:45 +02:00
|
|
|
protected $originalContent;
|
|
|
|
|
|
|
|
protected $content;
|
2024-04-17 11:41:10 +02:00
|
|
|
|
2024-04-20 23:27:47 +02:00
|
|
|
protected FilesystemAdapter $disk;
|
|
|
|
|
|
|
|
protected bool $isLoaded = false;
|
|
|
|
|
2024-04-17 11:41:10 +02:00
|
|
|
/**
|
2024-04-18 00:24:45 +02:00
|
|
|
* Constructor for the MetadataManager class.
|
|
|
|
*
|
|
|
|
* @param string $filename The filename where metadata is stored.
|
|
|
|
* @param disk $disk The disk abstraction provided by Laravel.
|
2024-04-17 11:41:10 +02:00
|
|
|
*/
|
2024-04-20 23:27:47 +02:00
|
|
|
public function __construct(protected string $filename, protected Bundle $bundle)
|
2024-04-17 11:41:10 +02:00
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
$this->disk = $bundle->getDisk();
|
|
|
|
|
2024-04-18 00:24:45 +02:00
|
|
|
$this->load();
|
2024-04-17 11:41:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-04-18 00:24:45 +02:00
|
|
|
* Loads metadata from disk using the disk, with caching to improve performance.
|
2024-04-17 11:41:10 +02:00
|
|
|
*/
|
2024-04-20 23:27:47 +02:00
|
|
|
public function load(bool $reload = false)
|
2024-04-17 11:41:10 +02:00
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
if (!$this->isLoaded || $reload) {
|
|
|
|
$data = $this->readFromDisk();
|
2024-04-18 00:24:45 +02:00
|
|
|
|
2024-04-20 23:27:47 +02:00
|
|
|
$this->originalContent = $data;
|
|
|
|
$this->content = $data;
|
|
|
|
$this->isLoaded = true;
|
|
|
|
}
|
2024-04-17 11:41:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-04-18 00:24:45 +02:00
|
|
|
* Checks if the content has been modified since it was last loaded or saved.
|
|
|
|
*
|
|
|
|
* @return bool True if the content is dirty (modified), false otherwise.
|
2024-04-17 11:41:10 +02:00
|
|
|
*/
|
|
|
|
public function isDirty(): bool
|
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
return collect($this->originalContent)->toJson() != collect($this->content)->toJson();
|
2024-04-17 11:41:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-04-18 00:24:45 +02:00
|
|
|
* Saves the metadata to disk if it has been modified (is dirty).
|
|
|
|
*
|
|
|
|
* @return bool True if the data was saved successfully, false otherwise.
|
2024-04-17 11:41:10 +02:00
|
|
|
*/
|
|
|
|
public function save(): bool
|
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
if (!$this->isDirty() || empty($this->content)) {
|
2024-04-17 11:41:10 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-04-20 23:27:47 +02:00
|
|
|
$this->writeToDisk($this->content);
|
2024-04-17 11:41:10 +02:00
|
|
|
|
2024-04-20 23:27:47 +02:00
|
|
|
$this->originalContent = $this->content;
|
2024-04-17 11:41:10 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2024-04-17 16:18:27 +02:00
|
|
|
|
2024-04-18 00:24:45 +02:00
|
|
|
/**
|
|
|
|
* Sets a metadata value for a specified key.
|
|
|
|
*
|
|
|
|
* @param mixed $key The key under which to store the value.
|
|
|
|
* @param mixed $value The value to store.
|
|
|
|
*/
|
|
|
|
public function set($key, $value)
|
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
data_set($this->content, $key, $value, true);
|
2024-04-18 00:24:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-04-18 11:41:29 +02:00
|
|
|
* Set many values at once
|
2024-04-18 00:24:45 +02:00
|
|
|
*/
|
2024-04-18 11:41:29 +02:00
|
|
|
public function setMany(array $array)
|
2024-04-17 16:18:27 +02:00
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
foreach ($array as $key => $value) {
|
|
|
|
$this->set($key, $value);
|
|
|
|
}
|
2024-04-18 11:41:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function merge(array $array)
|
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
$content = collect($this->content)->dot();
|
2024-04-18 11:41:29 +02:00
|
|
|
$newValue = collect($array)->dot();
|
2024-04-20 23:27:47 +02:00
|
|
|
$newContent = collect($content)->mergeRecursive($newValue)->undot()->toArray();
|
2024-04-18 11:41:29 +02:00
|
|
|
|
|
|
|
$this->content = $newContent;
|
2024-04-18 00:24:45 +02:00
|
|
|
}
|
2024-04-17 16:18:27 +02:00
|
|
|
|
2024-04-18 00:24:45 +02:00
|
|
|
/**
|
|
|
|
* Retrieves a metadata value by key.
|
|
|
|
*
|
|
|
|
* @param mixed $key The key of the value to retrieve.
|
|
|
|
* @param mixed $default The default value to return if the key does not exist.
|
|
|
|
* @return mixed The value of the specified key, or the default value.
|
|
|
|
*/
|
|
|
|
public function get($key, $default = null)
|
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
return data_get($this->content, $key, $default);
|
2024-04-17 16:18:27 +02:00
|
|
|
}
|
|
|
|
|
2024-04-18 00:24:45 +02:00
|
|
|
/**
|
|
|
|
* Retrieves all metadata as an associative array.
|
|
|
|
*
|
|
|
|
* @return array The content of the metadata.
|
|
|
|
*/
|
|
|
|
public function all()
|
2024-04-17 16:18:27 +02:00
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
return $this->content;
|
2024-04-17 16:18:27 +02:00
|
|
|
}
|
|
|
|
|
2024-04-18 00:24:45 +02:00
|
|
|
/**
|
|
|
|
* Removes a metadata entry by key.
|
|
|
|
*
|
|
|
|
* @param mixed $key The key of the entry to remove.
|
|
|
|
*/
|
|
|
|
public function remove($key)
|
2024-04-17 16:18:27 +02:00
|
|
|
{
|
2024-04-20 23:27:47 +02:00
|
|
|
collect($this->content)->forget($key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads metadata from disk. Caches the content to reduce file system reads.
|
|
|
|
*
|
|
|
|
* @return array The data read from the file.
|
|
|
|
*/
|
|
|
|
protected function readFromDisk()
|
|
|
|
{
|
|
|
|
$data = $this->disk->get($this->filename) ?? '[]';
|
|
|
|
|
|
|
|
return json_decode($data, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes the provided data to disk as JSON.
|
|
|
|
*
|
|
|
|
* @param array $data The data to write to disk.
|
|
|
|
*/
|
|
|
|
protected function writeToDisk(array $data)
|
|
|
|
{
|
|
|
|
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
|
|
|
|
|
|
$this->disk->put($this->filename, $json);
|
2024-04-17 16:18:27 +02:00
|
|
|
}
|
2024-04-17 11:41:10 +02:00
|
|
|
}
|