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 { interface IRegistry {
/** /**
* Register a new entry * Get the instance
* *
* @param string $name The entry name * If the instance is not already created then create it
* @param array $args The instance constructor arguments
* *
* @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 * Check if an entry name already exists
* *
* @param string $name The entry name * @param string $name The entry name
* *
* @return bool TRUE if the entry name already exists * @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 Throwable If an error occur
*
* @throws InvalidArgumentException If the entry name doesn't exist
* @throws Throwable If instantiating failed
*/ */
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; namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/** /**
* Default implementation for registry * Default implementation for registry
* *
@ -10,12 +13,75 @@ namespace jrosset\Singleton;
* @see IRegistry for interface * @see IRegistry for interface
*/ */
trait TRegistry { 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 * @inheritDoc
*/ */
public static function getInstance (string $name): self { public static function getInstance (?string $name = null): self {
return static::TRegistryBase_getInstance($name); $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 * @see IRegistryDefault for interface
*/ */
trait TRegistryDefault { trait TRegistryDefaultEntryName {
use TRegistryBase;
/** /**
* @var string|null The default entry name. NULL if not defined yet * @var string|null The default entry name. NULL if not defined yet
*/ */
private static ?string $registryDefaultEntryName = null; 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 { public static function getDefaultEntryName (): string {
if (static::$registryDefaultEntryName === null) { if (static::$registryDefaultEntryName === null) {
@ -29,16 +31,17 @@ trait TRegistryDefault {
return static::$registryDefaultEntryName; 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 { public static function setDefaultEntryName (string $name): void {
static::$registryDefaultEntryName = $name; 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 */ /** @noinspection PhpIllegalPsrClassPathInspection */
use jrosset\Singleton\IRegistry; use jrosset\Singleton\IRegistry;
use jrosset\Singleton\TRegistry; use jrosset\Singleton\TRegistryExternal;
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
class RegistryTest implements IRegistry { class RegistryTest implements IRegistry {
use TRegistry; use TRegistryExternal;
private int $cpt; private int $cpt;

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

Loading…
Cancel
Save