* @license http://opensource.org/licenses/MIT MIT */ declare(strict_types=1); namespace Ramsey\Uuid; use Ramsey\Uuid\Builder\DefaultUuidBuilder; use Ramsey\Uuid\Builder\DegradedUuidBuilder; use Ramsey\Uuid\Builder\UuidBuilderInterface; use Ramsey\Uuid\Codec\CodecInterface; use Ramsey\Uuid\Codec\GuidStringCodec; use Ramsey\Uuid\Codec\StringCodec; use Ramsey\Uuid\Converter\Number\BigNumberConverter; use Ramsey\Uuid\Converter\Number\DegradedNumberConverter; use Ramsey\Uuid\Converter\Number\GmpConverter; use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\Time\BigNumberTimeConverter; use Ramsey\Uuid\Converter\Time\DegradedTimeConverter; use Ramsey\Uuid\Converter\Time\GmpTimeConverter; use Ramsey\Uuid\Converter\Time\PhpTimeConverter; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Generator\PeclUuidTimeGenerator; use Ramsey\Uuid\Generator\RandomGeneratorFactory; use Ramsey\Uuid\Generator\RandomGeneratorInterface; use Ramsey\Uuid\Generator\TimeGeneratorFactory; use Ramsey\Uuid\Generator\TimeGeneratorInterface; use Ramsey\Uuid\Provider\Node\FallbackNodeProvider; use Ramsey\Uuid\Provider\Node\RandomNodeProvider; use Ramsey\Uuid\Provider\Node\SystemNodeProvider; use Ramsey\Uuid\Provider\NodeProviderInterface; use Ramsey\Uuid\Provider\Time\SystemTimeProvider; use Ramsey\Uuid\Provider\TimeProviderInterface; use Ramsey\Uuid\Validator\Validator; use Ramsey\Uuid\Validator\ValidatorInterface; /** * FeatureSet detects and exposes available features in the current environment * * A feature set is used by UuidFactory to determine the available features and * capabilities of the environment. */ class FeatureSet { /** * @var bool */ private $disableBigNumber = false; /** * @var bool */ private $disableGmp = false; /** * @var bool */ private $disable64Bit = false; /** * @var bool */ private $ignoreSystemNode = false; /** * @var bool */ private $enablePecl = false; /** * @var UuidBuilderInterface */ private $builder; /** * @var CodecInterface */ private $codec; /** * @var NodeProviderInterface */ private $nodeProvider; /** * @var NumberConverterInterface */ private $numberConverter; /** * @var TimeConverterInterface */ private $timeConverter; /** * @var RandomGeneratorInterface */ private $randomGenerator; /** * @var TimeGeneratorInterface */ private $timeGenerator; /** * @var ValidatorInterface */ private $validator; /** * @param bool $useGuids True build UUIDs using the GuidStringCodec * @param bool $force32Bit True to force the use of 32-bit functionality * (primarily for testing purposes) * @param bool $forceNoBigNumber True to disable the use of moontoast/math * (primarily for testing purposes) * @param bool $ignoreSystemNode True to disable attempts to check for the * system node ID (primarily for testing purposes) * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator * to generate version 1 UUIDs * @param bool $forceNoGmp True to disable the use of ext-gmp (primarily * for testing purposes) */ public function __construct( bool $useGuids = false, bool $force32Bit = false, bool $forceNoBigNumber = false, bool $ignoreSystemNode = false, bool $enablePecl = false, bool $forceNoGmp = false ) { $this->disableBigNumber = $forceNoBigNumber; $this->disableGmp = $forceNoGmp; $this->disable64Bit = $force32Bit; $this->ignoreSystemNode = $ignoreSystemNode; $this->enablePecl = $enablePecl; $this->numberConverter = $this->buildNumberConverter(); $this->timeConverter = $this->buildTimeConverter(); $this->builder = $this->buildUuidBuilder(); $this->codec = $this->buildCodec($useGuids); $this->nodeProvider = $this->buildNodeProvider(); $this->randomGenerator = $this->buildRandomGenerator(); $this->setTimeProvider(new SystemTimeProvider()); $this->validator = new Validator(); } /** * Returns the builder configured for this environment */ public function getBuilder(): UuidBuilderInterface { return $this->builder; } /** * Returns the codec configured for this environment */ public function getCodec(): CodecInterface { return $this->codec; } /** * Returns the node provider configured for this environment */ public function getNodeProvider(): NodeProviderInterface { return $this->nodeProvider; } /** * Returns the number converter configured for this environment */ public function getNumberConverter(): NumberConverterInterface { return $this->numberConverter; } /** * Returns the random generator configured for this environment */ public function getRandomGenerator(): RandomGeneratorInterface { return $this->randomGenerator; } /** * Returns the time generator configured for this environment */ public function getTimeGenerator(): TimeGeneratorInterface { return $this->timeGenerator; } /** * Returns the validator configured for this environment */ public function getValidator(): ValidatorInterface { return $this->validator; } /** * Sets the time provider to use in this environment */ public function setTimeProvider(TimeProviderInterface $timeProvider): void { $this->timeGenerator = $this->buildTimeGenerator($timeProvider); } /** * Set the validator to use in this environment */ public function setValidator(ValidatorInterface $validator): void { $this->validator = $validator; } /** * Returns a codec configured for this environment * * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec */ private function buildCodec(bool $useGuids = false): CodecInterface { if ($useGuids) { return new GuidStringCodec($this->builder); } return new StringCodec($this->builder); } /** * Returns a node provider configured for this environment */ private function buildNodeProvider(): NodeProviderInterface { if ($this->ignoreSystemNode) { return new RandomNodeProvider(); } return new FallbackNodeProvider([ new SystemNodeProvider(), new RandomNodeProvider(), ]); } /** * Returns a number converter configured for this environment */ private function buildNumberConverter(): NumberConverterInterface { if ($this->hasGmp()) { return new GmpConverter(); } if ($this->hasBigNumber()) { return new BigNumberConverter(); } return new DegradedNumberConverter(); } /** * Returns a random generator configured for this environment */ private function buildRandomGenerator(): RandomGeneratorInterface { return (new RandomGeneratorFactory())->getGenerator(); } /** * Returns a time generator configured for this environment * * @param TimeProviderInterface $timeProvider The time provider to use with * the time generator */ private function buildTimeGenerator(TimeProviderInterface $timeProvider): TimeGeneratorInterface { if ($this->enablePecl) { return new PeclUuidTimeGenerator(); } return (new TimeGeneratorFactory( $this->nodeProvider, $this->timeConverter, $timeProvider ))->getGenerator(); } /** * Returns a time converter configured for this environment */ private function buildTimeConverter(): TimeConverterInterface { if ($this->is64BitSystem()) { return new PhpTimeConverter(); } if ($this->hasGmp()) { return new GmpTimeConverter(); } if ($this->hasBigNumber()) { return new BigNumberTimeConverter(); } return new DegradedTimeConverter(); } /** * Returns a UUID builder configured for this environment */ private function buildUuidBuilder(): UuidBuilderInterface { if ($this->is64BitSystem()) { return new DefaultUuidBuilder($this->numberConverter, $this->timeConverter); } return new DegradedUuidBuilder($this->numberConverter, $this->timeConverter); } /** * Returns true if moontoast/math is available */ private function hasBigNumber(): bool { return class_exists('Moontoast\Math\BigNumber') && !$this->disableBigNumber; } /** * Returns true if ext-gmp is available */ private function hasGmp(): bool { return extension_loaded('gmp') && !$this->disableGmp; } /** * Returns true if the PHP build is 64-bit */ private function is64BitSystem(): bool { return PHP_INT_SIZE === 8 && !$this->disable64Bit; } }