Skip to content

Commit

Permalink
Added basic Pool implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mikadamczyk committed Sep 20, 2024
1 parent b9f1582 commit 6f6f21b
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 0 deletions.
110 changes: 110 additions & 0 deletions src/contracts/Pool/Pool.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Pool;

use Ibexa\Core\Base\Exceptions\InvalidArgumentException;

/**
* @template T of object
* @implements \Ibexa\Contracts\Core\Pool\PoolInterface<T>
*/
final class Pool implements PoolInterface
{
private const DEFAULT_EXCEPTION_MESSAGE_TEMPLATE = 'could not find %s for \'%s\'. Valid values are: %s';

private string $class;

/** @var iterable<string,T> */
private iterable $entries;

private string $exceptionArgumentName = '$alias';

private string $exceptionMessageTemplate = self::DEFAULT_EXCEPTION_MESSAGE_TEMPLATE;

/**
* @param iterable<string,T> $entries
*/
public function __construct(string $class, iterable $entries = [])
{
$this->class = $class;
$this->entries = $entries;
}

public function has(string $alias): bool
{
return $this->findEntry($alias) !== null;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
*
* @return T
*/
public function get(string $alias)
{
$entry = $this->findEntry($alias);

if ($entry === null) {
$entriesAliases = $this->getEntriesAliases();
$availableAliases = empty($entriesAliases) ? '' : "'" . implode("', '", $entriesAliases) . "'";

throw new InvalidArgumentException(
$this->exceptionArgumentName,
sprintf($this->exceptionMessageTemplate, $this->class, $alias, $availableAliases)
);
}

return $entry;
}

/**
* @return T|null
*/
private function findEntry(string $needle)
{
foreach ($this->entries as $type => $mapper) {
if ($needle === $type) {
return $mapper;
}
}

return null;
}

/**
* @return iterable<string,T>
*/
public function getEntries(): iterable
{
return $this->entries;
}

/**
* @return string[]
*/
private function getEntriesAliases(): array
{
$aliases = [];
foreach ($this->entries as $alias => $entry) {
$aliases[] = $alias;
}

return $aliases;
}

public function setExceptionArgumentName(string $exceptionArgumentName): void
{
$this->exceptionArgumentName = $exceptionArgumentName;
}

public function setExceptionMessageTemplate(string $exceptionMessageTemplate): void
{
$this->exceptionMessageTemplate = $exceptionMessageTemplate;
}
}
33 changes: 33 additions & 0 deletions src/contracts/Pool/PoolInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Pool;

/**
* @template T of object
*/
interface PoolInterface
{
public function has(string $alias): bool;

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
*
* @return T
*/
public function get(string $alias);

/**
* @return iterable<string,T>
*/
public function getEntries(): iterable;

public function setExceptionArgumentName(string $exceptionArgumentName): void;

public function setExceptionMessageTemplate(string $exceptionMessageTemplate): void;
}
71 changes: 71 additions & 0 deletions tests/lib/Pool/PoolTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Core\Pool;

use Ibexa\Contracts\Core\Pool\Pool;
use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use stdClass;

final class PoolTest extends TestCase
{
private stdClass $foo;

private stdClass $bar;

/** @var \Ibexa\Contracts\Core\Pool\Pool<\stdClass> */
private Pool $pool;

protected function setUp(): void
{
$this->foo = new stdClass();
$this->bar = new stdClass();
$entries = [
'foo' => $this->foo,
'bar' => $this->bar,
];

$this->pool = new Pool(
stdClass::class,
$entries
);
}

public function testHas(): void
{
self::assertTrue($this->pool->has('foo'));
self::assertFalse($this->pool->has('baz'));
}

public function testGet(): void
{
self::assertSame($this->foo, $this->pool->get('foo'));

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
sprintf(
"Argument '%s' is invalid: could not find stdClass for 'baz'. Valid values are: 'foo', 'bar'",
'$alias'
)
);

$this->pool->get('baz');
}

public function testGetEntries(): void
{
self::assertSame(
[
'foo' => $this->foo,
'bar' => $this->bar,
],
$this->pool->getEntries()
);
}
}

0 comments on commit 6f6f21b

Please sign in to comment.