refactor: standardize design

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-02-25 15:34:19 -05:00
parent dce16eff59
commit 80434e5476
14 changed files with 622 additions and 1595 deletions

View File

@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace KTXM\PeopleProviderLocal\Store\Personal;
namespace KTXM\ProviderLocalPeople\Store\Personal;
use KTXC\Db\DataStore;
use KTXF\Resource\Filter\Filter;
@@ -17,15 +17,13 @@ use KTXF\Resource\Range\Range;
use KTXF\Resource\Range\RangeType;
use KTXF\Resource\Sort\Sort;
use KTXF\Utile\UUID;
use KTXM\PeopleProviderLocal\Providers\Personal\Collection;
use KTXM\PeopleProviderLocal\Providers\Personal\Entity;
use KTXM\ProviderLocalPeople\Providers\Personal\CollectionResource;
use KTXM\ProviderLocalPeople\Providers\Personal\EntityResource;
class Store {
protected string $_CollectionTable = 'people_provider_local_collection';
protected string $_CollectionClass = 'KTXM\PeopleProviderLocal\Providers\Personal\Collection';
protected string $_EntityTable = 'people_provider_local_entity';
protected string $_EntityClass = 'KTXM\PeopleProviderLocal\Providers\Personal\Entity';
protected string $_ChronicleTable = 'people_provider_local_chronicle';
protected array $_CollectionFilterAttributeMap = [
@@ -145,8 +143,11 @@ class Store {
$cursor = $this->_store->selectCollection($this->_CollectionTable)->find($query, $options);
$list = [];
foreach ($cursor as $entry) {
$entry = (new Collection())->fromStore($entry);
$list[$entry->id()] = $entry;
$entry = $this->collectionFresh()->fromStore($entry);
$identifier = $entry->identifier();
if ($identifier !== null) {
$list[(string) $identifier] = $entry;
}
}
return $list;
}
@@ -177,9 +178,9 @@ class Store {
* @param string $userId user identifier
* @param string $identifier collection identifier
*
* @return Collection
* @return CollectionResource
*/
public function collectionFetch(string $tenantId, string $userId, string $identifier): ?Collection {
public function collectionFetch(string $tenantId, string $userId, string $identifier): ?CollectionResource {
$cursor = $this->_store->selectCollection($this->_CollectionTable)->findOne([
'tid' => $tenantId,
'uid' => $userId,
@@ -188,7 +189,7 @@ class Store {
if ($cursor === null) {
return null;
}
$entry = (new Collection())->fromStore($cursor);
$entry = $this->collectionFresh()->fromStore($cursor);
return $entry;
}
@@ -197,10 +198,10 @@ class Store {
*
* @since Release 1.0.0
*
* @return Collection
* @return CollectionResource
*/
public function collectionFresh(): Collection {
return new $this->_CollectionClass;
public function collectionFresh(): CollectionResource {
return new CollectionResource();
}
/**
@@ -209,24 +210,24 @@ class Store {
* @since Release 1.0.0
*
* @param string $userId user identifier
* @param Collection $entity
* @param CollectionResource $entity
*
* @return Collection
* @return CollectionResource
*/
public function collectionCreate(string $tenantId, string $userId, Collection $entity): Collection {
public function collectionCreate(string $tenantId, string $userId, CollectionResource $entity): CollectionResource {
// convert entity to store format
$data = $entity->toStore();
// prepare data for creation
$data['tid'] = $tenantId;
$data['uid'] = $userId;
$data['cid'] = UUID::v4();
$data['signature'] = isset($data['signature']) && is_numeric($data['signature']) ? (int)$data['signature'] : 0;
$data['createdOn'] = date('c');
$data['modifiedOn'] = $data['createdOn'];
// create entry
$result = $this->_store->selectCollection($this->_CollectionTable)->insertOne($data);
if ($result->getInsertedCount() === 1) {
$entity = new Collection();
$entity->fromStore($data);
$entity = $this->collectionFresh()->fromStore($data);
}
return $entity;
}
@@ -237,15 +238,18 @@ class Store {
* @since Release 1.0.0
*
* @param string $userId user identifier
* @param Collection $entity
* @param CollectionResource $entity
*
* @return Collection
* @return CollectionResource
*/
public function collectionModify(string $tenantId, string $userId, Collection $entity): Collection {
public function collectionModify(string $tenantId, string $userId, CollectionResource $entity): CollectionResource {
// convert entity to store format
$data = $entity->toStore();
// prepare data for modification
$cid = $entity->id();
$cid = $entity->identifier();
if ($cid === null) {
throw new \InvalidArgumentException('Collection identifier is required for modification');
}
$data['modifiedOn'] = date('c');
unset($data['_id'], $data['tid'], $data['uid'], $data['cid']);
// modify entry
@@ -261,12 +265,16 @@ class Store {
*
* @since Release 1.0.0
*
* @param Collection $entity
* @param CollectionResource $entity
*
* @return Collection
* @return CollectionResource
*/
public function collectionDestroy(string $tenantId, string $userId, Collection $entity): Collection {
return $this->collectionDestroyById($tenantId, $userId, $entity->id()) ? $entity : $entity;
public function collectionDestroy(string $tenantId, string $userId, CollectionResource $entity): CollectionResource {
$identifier = $entity->identifier();
if ($identifier === null) {
return $entity;
}
return $this->collectionDestroyById($tenantId, $userId, (string) $identifier) ? $entity : $entity;
}
/**
@@ -319,19 +327,32 @@ class Store {
}
// Apply range/pagination if provided
if ($range !== null && $range->type() === RangeType::TALLY) {
// For TALLY ranges, use position (skip) and tally (limit)
/** @var IRangeTally $rangeTally */
$rangeTally = $range;
$findOptions['skip'] = $rangeTally->getPosition();
$findOptions['limit'] = $rangeTally->getTally();
if ($range !== null) {
if ($range->type() === RangeType::TALLY) {
// For TALLY ranges, use position (skip) and tally (limit)
/** @var \KTXF\Resource\Range\IRangeTally $rangeTally */
$rangeTally = $range;
$findOptions['skip'] = $rangeTally->getPosition();
$findOptions['limit'] = $rangeTally->getTally();
} elseif ($range->type() === RangeType::DATE) {
// For DATE ranges, filter by date fields
/** @var \KTXF\Resource\Range\IRangeDate $rangeDate */
$rangeDate = $range;
$query['data.startsOn'] = [
'\$gte' => $rangeDate->getStart()->format('c'),
'\$lte' => $rangeDate->getEnd()->format('c')
];
}
}
$cursor = $this->_store->selectCollection($this->_EntityTable)->find($query, $findOptions);
$list = [];
foreach ($cursor as $entry) {
$entity = (new Entity())->fromStore($entry);
$list[$entity->id()] = $entity;
$entity = $this->entityFresh()->fromStore($entry);
$identifier = $entity->identifier();
if ($identifier !== null) {
$list[(string) $identifier] = $entity;
}
}
return $list;
}
@@ -381,7 +402,7 @@ class Store {
* @param string $collection collection identifier
* @param string ...$identifiers entity identifiers (eid UUID strings)
*
* @return array<Entity>
* @return array<EntityResource>
*/
public function entityFetch(string $tenantId, string $userId, string $collectionId, string ...$identifiers): array {
// Query for entities using eid field
@@ -394,8 +415,11 @@ class Store {
$list = [];
foreach ($cursor as $entry) {
$entity = (new Entity())->fromStore($entry);
$list[$entity->id()] = $entity;
$entity = $this->entityFresh()->fromStore($entry);
$identifier = $entity->identifier();
if ($identifier !== null) {
$list[(string) $identifier] = $entity;
}
}
return $list;
@@ -406,21 +430,12 @@ class Store {
*
* @since Release 1.0.0
*
* @return Entity
* @return EntityResource
*/
public function entityFresh(): Entity {
return new Entity();
public function entityFresh(): EntityResource {
return new EntityResource();
}
/**
* create a entity entry in the data store
*
* @since Release 1.0.0
*
* @param Entity $entity entity to create
*
* @return Entity
*/
/**
* create a entity entry in the data store
*
@@ -428,11 +443,11 @@ class Store {
*
* @param string $userId user identifier
* @param string $collection collection identifier
* @param Entity $entity entity to create
* @param EntityResource $entity entity to create
*
* @return Entity
* @return EntityResource
*/
public function entityCreate(string $tenantId, string $userId, string $collectionId, Entity $entity): Entity {
public function entityCreate(string $tenantId, string $userId, string $collectionId, EntityResource $entity): EntityResource {
// convert entity to store format
$data = $entity->toStore();
// assign identifiers and timestamps
@@ -449,7 +464,7 @@ class Store {
if ($result->getInsertedCount() === 1) {
$eid = $data['eid'];
$entity->fromStore(['eid' => $eid, 'tid' => $tenantId, 'uid' => $userId, 'cid' => $collectionId]);
$entity = $this->entityFresh()->fromStore($data);
// Chronicle the creation (operation 1)
$this->chronicleDocument($tenantId, $collectionId, $eid, 1);
}
@@ -465,11 +480,11 @@ class Store {
* @param string $userId user identifier
* @param string $collection collection identifier
* @param string $identifier entity identifier
* @param Entity $entity entity to modify
* @param EntityResource $entity entity to modify
*
* @return Entity
* @return EntityResource
*/
public function entityModify(string $tenantId, string $userId, string $collectionId, string $identifier, Entity $entity): Entity {
public function entityModify(string $tenantId, string $userId, string $collectionId, string $identifier, EntityResource $entity): EntityResource {
// convert entity to store format
$data = $entity->toStore();
$data['modifiedOn'] = date('c');
@@ -497,23 +512,26 @@ class Store {
*
* @param string $userId user identifier
* @param string $collection collection identifier
* @param Entity $entity entity to delete
* @param EntityResource $entity entity to delete
*
* @return Entity
* @return EntityResource
*/
public function entityDestroy(string $tenantId, string $userId, string $collectionId, Entity $entity): Entity {
$identifier = $entity->id();
public function entityDestroy(string $tenantId, string $userId, string $collectionId, EntityResource $entity): EntityResource {
$identifier = $entity->identifier();
if ($identifier === null) {
return $entity;
}
$result = $this->_store->selectCollection($this->_EntityTable)->deleteOne([
'tid' => $tenantId,
'uid' => $userId,
'cid' => $collectionId,
'eid' => $identifier
'eid' => (string) $identifier
]);
if ($result->getDeletedCount() === 1) {
// Chronicle the deletion (operation 3)
$this->chronicleDocument($tenantId, $collectionId, $identifier, 3);
$this->chronicleDocument($tenantId, $collectionId, (string) $identifier, 3);
}
return $entity;
@@ -560,12 +578,19 @@ class Store {
private function chronicleDocument(string $tid, string $cid, string $eid, int $operation): void {
// retrieve current token from collection
$collection = $this->_store->selectCollection($this->_CollectionTable)->findOne([
'tid' => $tid,
'cid' => $cid
], [
'projection' => ['signature' => 1, '_id' => 0]
]);
$signature = $collection['signature'] ?? 0;
$signatureRaw = $collection['signature'] ?? 0;
if (is_numeric($signatureRaw)) {
$signature = (int)$signatureRaw;
} else {
$decoded = is_string($signatureRaw) ? base64_decode($signatureRaw, true) : false;
$signature = (is_string($decoded) && is_numeric($decoded)) ? (int)$decoded : 0;
}
// document operation in chronicle
$this->_store->selectCollection($this->_ChronicleTable)->insertOne([
@@ -577,10 +602,10 @@ class Store {
'mutatedOn' => time(),
]);
// increment token atomically
// update signature as normalized numeric value
$this->_store->selectCollection($this->_CollectionTable)->updateOne(
['cid' => $cid],
['$inc' => ['signature' => 1]]
['tid' => $tid, 'cid' => $cid],
['$set' => ['signature' => $signature + 1]]
);
}