Registry: add internal vs external and better managing default entry

1.x 1.4.0
Julien Rosset 3 years ago
parent 6bf4ea2131
commit 22b17de4ca

@ -12,36 +12,27 @@ use Throwable;
*/
interface IRegistry {
/**
* Register a new entry
* Get the instance
*
* @param string $name The entry name
* @param array $args The instance constructor arguments
* If the instance is not already created then create it
*
* @return void
* @param string|null $name The entry name. Null if default entry name
*
* @throws InvalidArgumentException If the entry name already exists
* @return static The instance
*
* @throws InvalidArgumentException If the entry name doesn't exist
* @throws Throwable If instantiating failed
*/
public static function addEntry (string $name, ...$args): void;
public static function getInstance (?string $name = null): self;
/**
* Check if an entry name already exists
*
* @param string $name The entry name
*
* @return bool TRUE if the entry name already exists
*/
public static function hasEntry (string $name): bool;
/**
* Get the instance
*
* If the instance is not already created then create it
*
* @param string The entry name
*
* @return static The instance
*
* @throws InvalidArgumentException If the entry name doesn't exist
* @throws Throwable If instantiating failed
* @throws Throwable If an error occur
*/
public static function getInstance (string $name): self;
public static function hasEntry (string $name): bool;
}

@ -1,40 +0,0 @@
<?php
namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/**
* Interface for class implementing an instance register with a default entry name
*/
interface IRegistryDefault extends IRegistry {
/**
* The default entry name
*
* @return string The default entry name
*
* @throws InvalidArgumentException If the entry name isn't set
*/
public static function getDefaultEntryName (): string;
/**
* Set the default entry name
*
* <b>WARNING :</b> The entry name MUST already exists
*
* @param string $name The new default name
*
* @return void
*
* @throws InvalidArgumentException If the entry name doesn't exists
*/
public static function setDefaultEntryName (string $name): void;
/**
* @inheritDoc
*
* @throws InvalidArgumentException If the entry name doesn't exist or no default entry name
* @throws Throwable If instantiating failed
*/
public static function getInstance (?string $name = null): self;
}

@ -2,6 +2,9 @@
namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/**
* Default implementation for registry
*
@ -10,12 +13,75 @@ namespace jrosset\Singleton;
* @see IRegistry for interface
*/
trait TRegistry {
use TRegistryBase;
/**
* @var array[] The registry entries
*/
private static array $registerEntries = [];
/**
* @var static[] The current instances
*/
private static array $registryInstances = [];
/**
* Initialize registry entries
*
* Use {@see TRegistryBase::addEntry()} to add a new entry
*
* @return void
*
* @throws Throwable If an error occur
*/
protected static abstract function initializeEntries (): void;
/**
* Register a new entry
*
* @param string $name The entry name
* @param array $args The instance constructor arguments
*
* @return void
*
* @throws InvalidArgumentException If the entry name already exists
* @throws Throwable If an error occur
*/
protected static function addEntry (string $name, ...$args): void {
if (static::hasEntry($name)) {
throw new InvalidArgumentException('An entry with "' . $name . '" already exists');
}
static::$registerEntries[$name] = $args;
}
/**
* The default entry name
*
* @return string The default entry name
*
* @throws InvalidArgumentException If the entry name isn't set
*/
protected static function getDefaultEntryName (): string {
throw new InvalidArgumentException('No default entry name available');
}
/**
* @inheritDoc
*/
public static function hasEntry (string $name): bool {
if (count(static::$registerEntries[$name] ?? []) === 0) {
static::initializeEntries();
}
return isset(static::$registerEntries[$name]);
}
/**
* @inheritDoc
*/
public static function getInstance (string $name): self {
return static::TRegistryBase_getInstance($name);
public static function getInstance (?string $name = null): self {
$name ??= static::getDefaultEntryName();
if (!static::hasEntry($name)) {
throw new InvalidArgumentException('Unable to find entry "' . $name . '"');
}
if (!isset(static::$registryInstances[$name])) {
static::$registryInstances[$name] = new static(...static::$registerEntries[$name]);
}
return static::$registryInstances[$name];
}
}

@ -1,62 +0,0 @@
<?php
namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/**
* Default base implementation for registry
*
* Instance initialization through the constructor
*
* @see IRegistry for interface
*/
trait TRegistryBase {
/**
* @var array[] The registry entries
*/
private static array $registerEntries = [];
/**
* @var static[] The current instances
*/
private static array $registryInstances = [];
/**
* @inheritDoc
*/
public static function addEntry (string $name, ...$args): void {
if (static::hasEntry($name)) {
throw new InvalidArgumentException('An entry with "' . $name . '" already exists');
}
static::$registerEntries[$name] = $args;
}
/**
* @inheritDoc
*/
public static function hasEntry (string $name): bool {
return isset(static::$registerEntries[$name]);
}
/**
* Get the instance
*
* If the instance is not already created then create it
*
* @param string The entry name
*
* @return static The instance
*
* @throws InvalidArgumentException If the entry name doesn't exist
* @throws Throwable If instantiating failed
*/
public static function TRegistryBase_getInstance (string $name): self {
if (!static::hasEntry($name)) {
throw new InvalidArgumentException('Unable to find entry "' . $name . '"');
}
if (!isset(static::$registryInstances[$name])) {
static::$registryInstances[$name] = new static(...static::$registerEntries[$name]);
}
return static::$registryInstances[$name];
}
}

@ -11,16 +11,18 @@ use InvalidArgumentException;
*
* @see IRegistryDefault for interface
*/
trait TRegistryDefault {
use TRegistryBase;
trait TRegistryDefaultEntryName {
/**
* @var string|null The default entry name. NULL if not defined yet
*/
private static ?string $registryDefaultEntryName = null;
/**
* @inheritDoc
* The default entry name
*
* @return string The default entry name
*
* @throws InvalidArgumentException If the entry name isn't set
*/
public static function getDefaultEntryName (): string {
if (static::$registryDefaultEntryName === null) {
@ -29,16 +31,17 @@ trait TRegistryDefault {
return static::$registryDefaultEntryName;
}
/**
* @inheritDoc
* Set the default entry name
*
* <b>WARNING :</b> The entry name MUST already exists
*
* @param string $name The new default name
*
* @return void
*
* @throws InvalidArgumentException If the entry name doesn't exists
*/
public static function setDefaultEntryName (string $name): void {
static::$registryDefaultEntryName = $name;
}
/**
* @inheritDoc
*/
public static function getInstance (?string $name = null): self {
return static::TRegistryBase_getInstance($name ?? static::getDefaultEntryName());
}
}

@ -0,0 +1,29 @@
<?php
namespace jrosset\Singleton;
/**
* Default implementation for registry with external added entries
*
* Instance initialization through the constructor
*
* @see IRegistry for interface
*/
trait TRegistryExternal {
use TRegistry {
addEntry as protected TRegistry_addEntry;
}
/**
* @inheritDoc
*/
public static function addEntry (string $name, ...$args): void {
self::TRegistry_addEntry($name, ...$args);
}
/**
* @inheritDoc
*/
protected static function initializeEntries (): void {
// Do nothing : add entry is now public for external added entries
}
}

@ -4,12 +4,12 @@
/** @noinspection PhpIllegalPsrClassPathInspection */
use jrosset\Singleton\IRegistry;
use jrosset\Singleton\TRegistry;
use jrosset\Singleton\TRegistryExternal;
require_once __DIR__ . '/../vendor/autoload.php';
class RegistryTest implements IRegistry {
use TRegistry;
use TRegistryExternal;
private int $cpt;

@ -3,13 +3,16 @@
/** @noinspection PhpIllegalPsrClassPathInspection */
use jrosset\Singleton\IRegistryDefault;
use jrosset\Singleton\TRegistryDefault;
use jrosset\Singleton\IRegistry;
use jrosset\Singleton\TRegistryDefaultEntryName;
use jrosset\Singleton\TRegistryExternal;
require_once __DIR__ . '/../vendor/autoload.php';
class RegistryDefaultTest implements IRegistryDefault {
use TRegistryDefault;
class RegistryDefaultTest implements IRegistry {
use TRegistryExternal, TRegistryDefaultEntryName {
TRegistryDefaultEntryName::getDefaultEntryName insteadof TRegistryExternal;
}
private int $cpt;

Loading…
Cancel
Save