Improved metadata and attachments management
This commit is contained in:
parent
7fcb52964c
commit
cb69910188
|
@ -55,6 +55,23 @@ public function addToHistory(string $name, array $data): string
|
||||||
return $reference;
|
return $reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides direct access to underlying manager for better control
|
||||||
|
*/
|
||||||
|
public function manager(): MetadataManager
|
||||||
|
{
|
||||||
|
return $this->manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or replace attachment with specified reference. Will replace existing
|
||||||
|
* data
|
||||||
|
*/
|
||||||
|
public function upsert(string $reference, array $data)
|
||||||
|
{
|
||||||
|
$this->manager['files'][$reference] = $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single file to the bundle
|
* Add a single file to the bundle
|
||||||
*/
|
*/
|
||||||
|
@ -87,6 +104,14 @@ public function exists()
|
||||||
return $this->disk->exists($this->metadataFilePath);
|
return $this->disk->exists($this->metadataFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data from disk
|
||||||
|
*/
|
||||||
|
public function load()
|
||||||
|
{
|
||||||
|
$this->manager->load();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store file on disk
|
* Store file on disk
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,6 +18,18 @@ public function __construct(protected string $path, protected FilesystemAdapter
|
||||||
{
|
{
|
||||||
$this->path = Str::start(Str::finish($this->path, '/'), '/');
|
$this->path = Str::start(Str::finish($this->path, '/'), '/');
|
||||||
$this->dataDir = $this->path . 'data/';
|
$this->dataDir = $this->path . 'data/';
|
||||||
|
|
||||||
|
$this->registerDefaultManagers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load everything
|
||||||
|
*/
|
||||||
|
public function load()
|
||||||
|
{
|
||||||
|
$this->loadAttachments();
|
||||||
|
$this->loadMetadata();
|
||||||
|
$this->loadMarkdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +42,19 @@ public function save()
|
||||||
$this->saveMarkdown();
|
$this->saveMarkdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register default managers
|
||||||
|
*/
|
||||||
|
private function registerDefaultManagers()
|
||||||
|
{
|
||||||
|
$this->markdown();
|
||||||
|
$this->metadata();
|
||||||
|
$this->metadata('metadata');
|
||||||
|
$this->attachments(AttachmentsManager::Images);
|
||||||
|
$this->attachments(AttachmentsManager::Sounds);
|
||||||
|
$this->attachments(AttachmentsManager::Videos);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a complete filename prefixed with bundle's path
|
* Get a complete filename prefixed with bundle's path
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,6 +29,16 @@ public function exists()
|
||||||
return $this->disk->exists($this->filename);
|
return $this->disk->exists($this->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load markdown file
|
||||||
|
*/
|
||||||
|
public function load()
|
||||||
|
{
|
||||||
|
$content = $this->disk->get($this->filename);
|
||||||
|
|
||||||
|
$this->set($content);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return current markdown content
|
* Return current markdown content
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,55 +2,70 @@
|
||||||
|
|
||||||
namespace App\Classes;
|
namespace App\Classes;
|
||||||
|
|
||||||
use ArrayAccess;
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class MetadataManager implements ArrayAccess
|
/**
|
||||||
|
* 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
|
||||||
{
|
{
|
||||||
/**
|
protected $originalContent;
|
||||||
* Original metadata content
|
|
||||||
*/
|
protected $content;
|
||||||
private array $originalContent = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current metadata content
|
* Constructor for the MetadataManager class.
|
||||||
|
*
|
||||||
|
* @param string $filename The filename where metadata is stored.
|
||||||
|
* @param disk $disk The disk abstraction provided by Laravel.
|
||||||
*/
|
*/
|
||||||
private array $content = [];
|
|
||||||
|
|
||||||
public function __construct(protected string $filename, protected FilesystemAdapter $disk)
|
public function __construct(protected string $filename, protected FilesystemAdapter $disk)
|
||||||
{
|
{
|
||||||
|
$this->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a boolean value indicating if the file actually exists on disk
|
* Loads metadata from disk using the disk, with caching to improve performance.
|
||||||
*/
|
*/
|
||||||
public function exists()
|
public function load()
|
||||||
{
|
{
|
||||||
return $this->disk->exists($this->filename);
|
$data = $this->readFromDisk();
|
||||||
|
|
||||||
|
$this->originalContent = new Collection($data);
|
||||||
|
$this->content = new Collection($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a new array of values
|
* Reads metadata from disk. Caches the content to reduce file system reads.
|
||||||
|
*
|
||||||
|
* @return array The data read from the file.
|
||||||
*/
|
*/
|
||||||
public function set(array $content): void
|
protected function readFromDisk()
|
||||||
{
|
{
|
||||||
$this->content = $content;
|
$data = $this->disk->get($this->filename);
|
||||||
|
|
||||||
|
return json_decode($data, true) ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a boolean indicating if the file has changed since it was loaded
|
* 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.
|
||||||
*/
|
*/
|
||||||
public function isDirty(): bool
|
public function isDirty(): bool
|
||||||
{
|
{
|
||||||
$original = collect($this->originalContent);
|
return $this->originalContent->toJson() != $this->content->toJson();
|
||||||
$current = collect($this->content);
|
|
||||||
|
|
||||||
return !$original->diffAssoc($current)->isEmpty() || !$current->diffAssoc($original)->isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store file on disk
|
* Saves the metadata to disk if it has been modified (is dirty).
|
||||||
|
*
|
||||||
|
* @return bool True if the data was saved successfully, false otherwise.
|
||||||
*/
|
*/
|
||||||
public function save(): bool
|
public function save(): bool
|
||||||
{
|
{
|
||||||
|
@ -58,40 +73,75 @@ public function save(): bool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = json_encode($this->content, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
$this->writeToDisk($this->content->all());
|
||||||
|
|
||||||
$this->disk->put($this->filename, $json);
|
$this->originalContent = new Collection($this->content->all());
|
||||||
|
|
||||||
$this->originalContent = $this->content;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function offsetExists(mixed $offset): bool
|
/**
|
||||||
|
* Writes the provided data to disk as JSON.
|
||||||
|
*
|
||||||
|
* @param array $data The data to write to disk.
|
||||||
|
*/
|
||||||
|
protected function writeToDisk(array $data)
|
||||||
{
|
{
|
||||||
return isset($this->content[$offset]);
|
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
$this->disk->put($this->filename, $json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &offsetGet(mixed $offset): mixed
|
/**
|
||||||
|
* 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)
|
||||||
{
|
{
|
||||||
if (!isset($this->content[$offset])) {
|
$this->content->put($key, $value);
|
||||||
$this->content[$offset] = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->content[$offset];
|
/**
|
||||||
}
|
* Sets multiple metadata at once.
|
||||||
|
*/
|
||||||
public function offsetSet(mixed $offset, mixed $value): void
|
public function setMany(array $array)
|
||||||
{
|
{
|
||||||
if (is_null($offset)) {
|
foreach ($array as $key => $value) {
|
||||||
$this->content[] = $value;
|
$this->content->put($key, $value);
|
||||||
} else {
|
|
||||||
$this->content[$offset] = $value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function offsetUnset(mixed $offset): void
|
/**
|
||||||
|
* 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)
|
||||||
{
|
{
|
||||||
unset($this->content[$offset]);
|
return $this->content->get($key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all metadata as an associative array.
|
||||||
|
*
|
||||||
|
* @return array The content of the metadata.
|
||||||
|
*/
|
||||||
|
public function all()
|
||||||
|
{
|
||||||
|
return $this->content->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a metadata entry by key.
|
||||||
|
*
|
||||||
|
* @param mixed $key The key of the entry to remove.
|
||||||
|
*/
|
||||||
|
public function remove($key)
|
||||||
|
{
|
||||||
|
$this->content->forget($key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,16 @@ private function registerAttachmentsManager(string $kind): AttachmentsManager
|
||||||
return $this->attachmentsManagers[$kind];
|
return $this->attachmentsManagers[$kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all attachments files
|
||||||
|
*/
|
||||||
|
private function loadAttachments()
|
||||||
|
{
|
||||||
|
foreach ($this->attachmentsManagers as $manager) {
|
||||||
|
$manager->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save all attachments files that needs to be
|
* Save all attachments files that needs to be
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,6 +22,16 @@ private function registerMarkdownManager(string $filename): MarkdownManager
|
||||||
return $this->markdownManagers[$filename];
|
return $this->markdownManagers[$filename];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all markdown files at once
|
||||||
|
*/
|
||||||
|
private function loadMarkdown()
|
||||||
|
{
|
||||||
|
foreach ($this->markdownManagers as $manager) {
|
||||||
|
$manager->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save all markdown files that needs to be
|
* Save all markdown files that needs to be
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,6 +22,16 @@ private function registerMetadataManager(string $filename): MetadataManager
|
||||||
return $this->metadataManagers[$filename];
|
return $this->metadataManagers[$filename];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all metadata files at once
|
||||||
|
*/
|
||||||
|
private function loadMetadata()
|
||||||
|
{
|
||||||
|
foreach ($this->metadataManagers as $manager) {
|
||||||
|
$manager->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save all metadata files that needs to be
|
* Save all metadata files that needs to be
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -37,7 +37,7 @@ public function createBundle(): string
|
||||||
}
|
}
|
||||||
|
|
||||||
$bundle->markdown()->set('');
|
$bundle->markdown()->set('');
|
||||||
$bundle->metadata()->set([
|
$bundle->metadata()->setMany([
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'date' => $date->toIso8601String(),
|
'date' => $date->toIso8601String(),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -46,10 +46,10 @@ public function createBundle(): string
|
||||||
|
|
||||||
$ref = $bundle->attachments(AttachmentsManager::Images)->addToHistory('screenshot', [
|
$ref = $bundle->attachments(AttachmentsManager::Images)->addToHistory('screenshot', [
|
||||||
'contents' => $screenshot,
|
'contents' => $screenshot,
|
||||||
'filename' => sprintf('screenshot-%s.jpg', now()->format('Y-m-d')),
|
'url' => sprintf('screenshot-%s.jpg', now()->format('Y-m-d')),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$bundle->metadata()->set([
|
$bundle->metadata()->setMany([
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'date' => $date->toIso8601String(),
|
'date' => $date->toIso8601String(),
|
||||||
'cover' => $ref,
|
'cover' => $ref,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user