Skip to content

Commit

Permalink
class-based api
Browse files Browse the repository at this point in the history
  • Loading branch information
nekufa committed Oct 10, 2024
1 parent f546313 commit d30d885
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 10 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,30 @@ class Policy
}
}

$policy = $mapper->createSpace('policy');
$policy = $mapper->createSpace('policy', ['if_not_exists' => true]);
$policy->setClass(Policy::class, 'initialize'); // use custom initialize method
$policy->migrate();

/**
* mapper access using class name
*/
class Login
{
public function __construct(
public int $id,
public string $username,
public string $password,
) {
}

public static function initSchema(\Tarantool\Mapper\Space $space)
{
$space->addIndex(['username'], ['unique' => true]);
}
}

$nekufa = $mapper->findOrCreate(Login::class, ['username' = 'nekufa']);
$mapper->update(Login::class, $nekufa, ['password' => password_hash("secret")]);
```

## Working with the data
Expand Down
51 changes: 49 additions & 2 deletions src/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tarantool\Mapper;

use Psr\Cache\CacheItemPoolInterface;
use ReflectionClass;
use Tarantool\Client\Client;
use Tarantool\Client\Exception\RequestFailed;
use Tarantool\Client\Schema\Criteria;
Expand All @@ -14,6 +15,7 @@ class Mapper
{
use Api;

private array $classNames = [];
private array $spaceId = [];
private array $spaces = [];
private int $schemaId = 0;
Expand All @@ -40,6 +42,7 @@ public function call(string $query, array $params = [])

public function createSpace(string $space, array $options = []): Space
{
$space = $this->getClassSpace($space);
$this->client->evaluate('box.schema.space.create(...)', $space, $options);
return $this->getSpace($space);
}
Expand Down Expand Up @@ -128,13 +131,33 @@ public function getChanges(): array
return $this->middleware->getChanges();
}

public function getClassSpace(int|string $class): int|string
{
if (!is_integer($class) && class_exists($class)) {
if (!array_key_exists($class, $this->classNames)) {
$this->registerClass($class);
}
return $this->classNames[$class];
}

return $class;
}

public function getSpace(int|string $id): Space
{
if (!count($this->spaces)) {
$this->setSchemaId(0);
}

return is_string($id) ? $this->getSpace($this->spaceId[$id]) : $this->spaces[$id];
$space = $this->getClassSpace($id);
if ($space !== $id) {
if (!$this->hasSpace($space)) {
$spaceInstance = $this->createSpace($space);
$spaceInstance->setClass($id);
$spaceInstance->migrate();
}
}
return is_string($space) ? $this->getSpace($this->spaceId[$space]) : $this->spaces[$space];
}

public function getSpaces(): array
Expand All @@ -144,7 +167,7 @@ public function getSpaces(): array

public function hasSpace(string $space): bool
{
return array_key_exists($space, $this->spaceId);
return array_key_exists($this->getClassSpace($space), $this->spaceId);
}

public function migrate(array $migrations = []): void
Expand All @@ -163,6 +186,26 @@ public function migrate(array $migrations = []): void
array_map(fn(Migration $migration) => $migration->afterSchema($this), $instances);
}

public function registerClass(string $class)
{
if (!array_key_exists($class, $this->classNames)) {
if (method_exists($class, 'getSpaceName')) {
$space = call_user_func([$class, 'getSpaceName']);
} else {
$space = preg_replace(
['/(?<=[^A-Z])([A-Z])/', '/(?<=[^0-9])([0-9])/'],
'_$0',
(new ReflectionClass($class))->getShortName(),
);
$space = strtolower($space);
}
if (array_key_exists($space, $this->spaceId)) {
$this->spaces[$this->spaceId[$space]]->setClass($class);
}
$this->classNames[$class] = strtolower($space);
}
}

public function setSchemaId(int $schemaId)
{
if (!$this->schemaId || $this->schemaId !== $schemaId) {
Expand All @@ -186,6 +229,10 @@ public function setSchemaId(int $schemaId)
$this->spaces[$row['id']]->setFormat($row['format']);
}
$this->spaceId[$row['name']] = $row['id'];

if (array_search($row['name'], $this->classNames)) {
$this->spaces[$row['id']]->setClass(array_search($row['name'], $this->classNames));
}
}

foreach (array_keys($this->spaces) as $id) {
Expand Down
35 changes: 28 additions & 7 deletions tests/MapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ public function createMapper(
return $mapper;
}

public function testClassBased()
{
$mapper = $this->createMapper();

$row = $mapper->findOrCreate(TypedConstructor::class, []);
$this->assertEquals($row, $mapper->findOne('constructor'));

$mapper = $this->createMapper(dropUserSpaces: false);
$mapper->registerClass(TypedConstructor::class);
$this->assertInstanceOf(TypedConstructor::class, $mapper->findOne('constructor'));
$this->assertEquals($row, $mapper->findOne('constructor'));
}

public function testUpdateStringPrimaryKey()
{
$mapper = $this->createMapper();
Expand Down Expand Up @@ -323,19 +336,27 @@ public function testSpaces()


$userTypes = [
'constructor' => TypedConstructor::class,
'properties' => TypedProperties::class,
'constructor' => TypedConstructor::class, // static space name
'typed_properties' => TypedProperties::class, // class basd space name
];

foreach ($userTypes as $name => $type) {
foreach ([$name, $type] as $target) {
$space = $mapper->createSpace($target);
$space->setClass($type);
$space->migrate();
$space->migrate();
$this->assertSame($space->getName(), $name);

$this->assertSame($space, $mapper->createSpace($target, ['if_not_exists' => true]));
$this->assertSame($space, $mapper->getSpace($space->getId()));
$this->assertCount(2, $mapper->find('_vindex', ['id' => $space->getId()]));
$space->drop();
}

$space = $mapper->createSpace($name);
$space->setClass($type);
$space->migrate();
$space->migrate();

$this->assertSame($space, $mapper->createSpace($name, ['if_not_exists' => true]));
$this->assertSame($space, $mapper->getSpace($space->getId()));
$this->assertCount(2, $mapper->find('_vindex', ['id' => $space->getId()]));
}

$space = $mapper->createSpace('array');
Expand Down
5 changes: 5 additions & 0 deletions tests/TypedConstructor.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public function __construct(
) {
}

public static function getSpaceName(): string
{
return 'constructor';
}

public static function initSchema(Space $space)
{
$space->addIndex(['name'], ['unique' => false]);
Expand Down

0 comments on commit d30d885

Please sign in to comment.