FeatureSet.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <?php
  2. /**
  3. * This file is part of the ramsey/uuid library
  4. *
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. *
  8. * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
  9. * @license http://opensource.org/licenses/MIT MIT
  10. */
  11. declare(strict_types=1);
  12. namespace Ramsey\Uuid;
  13. use Ramsey\Uuid\Builder\FallbackBuilder;
  14. use Ramsey\Uuid\Builder\UuidBuilderInterface;
  15. use Ramsey\Uuid\Codec\CodecInterface;
  16. use Ramsey\Uuid\Codec\GuidStringCodec;
  17. use Ramsey\Uuid\Codec\StringCodec;
  18. use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
  19. use Ramsey\Uuid\Converter\NumberConverterInterface;
  20. use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
  21. use Ramsey\Uuid\Converter\Time\PhpTimeConverter;
  22. use Ramsey\Uuid\Converter\TimeConverterInterface;
  23. use Ramsey\Uuid\Generator\DceSecurityGenerator;
  24. use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface;
  25. use Ramsey\Uuid\Generator\NameGeneratorFactory;
  26. use Ramsey\Uuid\Generator\NameGeneratorInterface;
  27. use Ramsey\Uuid\Generator\PeclUuidNameGenerator;
  28. use Ramsey\Uuid\Generator\PeclUuidRandomGenerator;
  29. use Ramsey\Uuid\Generator\PeclUuidTimeGenerator;
  30. use Ramsey\Uuid\Generator\RandomGeneratorFactory;
  31. use Ramsey\Uuid\Generator\RandomGeneratorInterface;
  32. use Ramsey\Uuid\Generator\TimeGeneratorFactory;
  33. use Ramsey\Uuid\Generator\TimeGeneratorInterface;
  34. use Ramsey\Uuid\Generator\UnixTimeGenerator;
  35. use Ramsey\Uuid\Guid\GuidBuilder;
  36. use Ramsey\Uuid\Math\BrickMathCalculator;
  37. use Ramsey\Uuid\Math\CalculatorInterface;
  38. use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
  39. use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
  40. use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
  41. use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
  42. use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
  43. use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
  44. use Ramsey\Uuid\Provider\NodeProviderInterface;
  45. use Ramsey\Uuid\Provider\Time\SystemTimeProvider;
  46. use Ramsey\Uuid\Provider\TimeProviderInterface;
  47. use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
  48. use Ramsey\Uuid\Validator\GenericValidator;
  49. use Ramsey\Uuid\Validator\ValidatorInterface;
  50. use const PHP_INT_SIZE;
  51. /**
  52. * FeatureSet detects and exposes available features in the current environment
  53. *
  54. * A feature set is used by UuidFactory to determine the available features and
  55. * capabilities of the environment.
  56. */
  57. class FeatureSet
  58. {
  59. private ?TimeProviderInterface $timeProvider = null;
  60. private CalculatorInterface $calculator;
  61. private CodecInterface $codec;
  62. private DceSecurityGeneratorInterface $dceSecurityGenerator;
  63. private NameGeneratorInterface $nameGenerator;
  64. private NodeProviderInterface $nodeProvider;
  65. private NumberConverterInterface $numberConverter;
  66. private RandomGeneratorInterface $randomGenerator;
  67. private TimeConverterInterface $timeConverter;
  68. private TimeGeneratorInterface $timeGenerator;
  69. private TimeGeneratorInterface $unixTimeGenerator;
  70. private UuidBuilderInterface $builder;
  71. private ValidatorInterface $validator;
  72. /**
  73. * @param bool $useGuids True build UUIDs using the GuidStringCodec
  74. * @param bool $force32Bit True to force the use of 32-bit functionality
  75. * (primarily for testing purposes)
  76. * @param bool $forceNoBigNumber (obsolete)
  77. * @param bool $ignoreSystemNode True to disable attempts to check for the
  78. * system node ID (primarily for testing purposes)
  79. * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator
  80. * to generate version 1 UUIDs
  81. */
  82. public function __construct(
  83. bool $useGuids = false,
  84. private bool $force32Bit = false,
  85. bool $forceNoBigNumber = false,
  86. private bool $ignoreSystemNode = false,
  87. private bool $enablePecl = false
  88. ) {
  89. $this->randomGenerator = $this->buildRandomGenerator();
  90. $this->setCalculator(new BrickMathCalculator());
  91. $this->builder = $this->buildUuidBuilder($useGuids);
  92. $this->codec = $this->buildCodec($useGuids);
  93. $this->nodeProvider = $this->buildNodeProvider();
  94. $this->nameGenerator = $this->buildNameGenerator();
  95. $this->setTimeProvider(new SystemTimeProvider());
  96. $this->setDceSecurityProvider(new SystemDceSecurityProvider());
  97. $this->validator = new GenericValidator();
  98. assert($this->timeProvider !== null);
  99. $this->unixTimeGenerator = $this->buildUnixTimeGenerator();
  100. }
  101. /**
  102. * Returns the builder configured for this environment
  103. */
  104. public function getBuilder(): UuidBuilderInterface
  105. {
  106. return $this->builder;
  107. }
  108. /**
  109. * Returns the calculator configured for this environment
  110. */
  111. public function getCalculator(): CalculatorInterface
  112. {
  113. return $this->calculator;
  114. }
  115. /**
  116. * Returns the codec configured for this environment
  117. */
  118. public function getCodec(): CodecInterface
  119. {
  120. return $this->codec;
  121. }
  122. /**
  123. * Returns the DCE Security generator configured for this environment
  124. */
  125. public function getDceSecurityGenerator(): DceSecurityGeneratorInterface
  126. {
  127. return $this->dceSecurityGenerator;
  128. }
  129. /**
  130. * Returns the name generator configured for this environment
  131. */
  132. public function getNameGenerator(): NameGeneratorInterface
  133. {
  134. return $this->nameGenerator;
  135. }
  136. /**
  137. * Returns the node provider configured for this environment
  138. */
  139. public function getNodeProvider(): NodeProviderInterface
  140. {
  141. return $this->nodeProvider;
  142. }
  143. /**
  144. * Returns the number converter configured for this environment
  145. */
  146. public function getNumberConverter(): NumberConverterInterface
  147. {
  148. return $this->numberConverter;
  149. }
  150. /**
  151. * Returns the random generator configured for this environment
  152. */
  153. public function getRandomGenerator(): RandomGeneratorInterface
  154. {
  155. return $this->randomGenerator;
  156. }
  157. /**
  158. * Returns the time converter configured for this environment
  159. */
  160. public function getTimeConverter(): TimeConverterInterface
  161. {
  162. return $this->timeConverter;
  163. }
  164. /**
  165. * Returns the time generator configured for this environment
  166. */
  167. public function getTimeGenerator(): TimeGeneratorInterface
  168. {
  169. return $this->timeGenerator;
  170. }
  171. /**
  172. * Returns the Unix Epoch time generator configured for this environment
  173. */
  174. public function getUnixTimeGenerator(): TimeGeneratorInterface
  175. {
  176. return $this->unixTimeGenerator;
  177. }
  178. /**
  179. * Returns the validator configured for this environment
  180. */
  181. public function getValidator(): ValidatorInterface
  182. {
  183. return $this->validator;
  184. }
  185. /**
  186. * Sets the calculator to use in this environment
  187. */
  188. public function setCalculator(CalculatorInterface $calculator): void
  189. {
  190. $this->calculator = $calculator;
  191. $this->numberConverter = $this->buildNumberConverter($calculator);
  192. $this->timeConverter = $this->buildTimeConverter($calculator);
  193. /** @psalm-suppress RedundantPropertyInitializationCheck */
  194. if (isset($this->timeProvider)) {
  195. $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
  196. }
  197. }
  198. /**
  199. * Sets the DCE Security provider to use in this environment
  200. */
  201. public function setDceSecurityProvider(DceSecurityProviderInterface $dceSecurityProvider): void
  202. {
  203. $this->dceSecurityGenerator = $this->buildDceSecurityGenerator($dceSecurityProvider);
  204. }
  205. /**
  206. * Sets the node provider to use in this environment
  207. */
  208. public function setNodeProvider(NodeProviderInterface $nodeProvider): void
  209. {
  210. $this->nodeProvider = $nodeProvider;
  211. if (isset($this->timeProvider)) {
  212. $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
  213. }
  214. }
  215. /**
  216. * Sets the time provider to use in this environment
  217. */
  218. public function setTimeProvider(TimeProviderInterface $timeProvider): void
  219. {
  220. $this->timeProvider = $timeProvider;
  221. $this->timeGenerator = $this->buildTimeGenerator($timeProvider);
  222. }
  223. /**
  224. * Set the validator to use in this environment
  225. */
  226. public function setValidator(ValidatorInterface $validator): void
  227. {
  228. $this->validator = $validator;
  229. }
  230. /**
  231. * Returns a codec configured for this environment
  232. *
  233. * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec
  234. */
  235. private function buildCodec(bool $useGuids = false): CodecInterface
  236. {
  237. if ($useGuids) {
  238. return new GuidStringCodec($this->builder);
  239. }
  240. return new StringCodec($this->builder);
  241. }
  242. /**
  243. * Returns a DCE Security generator configured for this environment
  244. */
  245. private function buildDceSecurityGenerator(
  246. DceSecurityProviderInterface $dceSecurityProvider
  247. ): DceSecurityGeneratorInterface {
  248. return new DceSecurityGenerator(
  249. $this->numberConverter,
  250. $this->timeGenerator,
  251. $dceSecurityProvider
  252. );
  253. }
  254. /**
  255. * Returns a node provider configured for this environment
  256. */
  257. private function buildNodeProvider(): NodeProviderInterface
  258. {
  259. if ($this->ignoreSystemNode) {
  260. return new RandomNodeProvider();
  261. }
  262. return new FallbackNodeProvider([
  263. new SystemNodeProvider(),
  264. new RandomNodeProvider(),
  265. ]);
  266. }
  267. /**
  268. * Returns a number converter configured for this environment
  269. */
  270. private function buildNumberConverter(CalculatorInterface $calculator): NumberConverterInterface
  271. {
  272. return new GenericNumberConverter($calculator);
  273. }
  274. /**
  275. * Returns a random generator configured for this environment
  276. */
  277. private function buildRandomGenerator(): RandomGeneratorInterface
  278. {
  279. if ($this->enablePecl) {
  280. return new PeclUuidRandomGenerator();
  281. }
  282. return (new RandomGeneratorFactory())->getGenerator();
  283. }
  284. /**
  285. * Returns a time generator configured for this environment
  286. *
  287. * @param TimeProviderInterface $timeProvider The time provider to use with
  288. * the time generator
  289. */
  290. private function buildTimeGenerator(TimeProviderInterface $timeProvider): TimeGeneratorInterface
  291. {
  292. if ($this->enablePecl) {
  293. return new PeclUuidTimeGenerator();
  294. }
  295. return (new TimeGeneratorFactory(
  296. $this->nodeProvider,
  297. $this->timeConverter,
  298. $timeProvider
  299. ))->getGenerator();
  300. }
  301. /**
  302. * Returns a Unix Epoch time generator configured for this environment
  303. */
  304. private function buildUnixTimeGenerator(): TimeGeneratorInterface
  305. {
  306. return new UnixTimeGenerator($this->randomGenerator);
  307. }
  308. /**
  309. * Returns a name generator configured for this environment
  310. */
  311. private function buildNameGenerator(): NameGeneratorInterface
  312. {
  313. if ($this->enablePecl) {
  314. return new PeclUuidNameGenerator();
  315. }
  316. return (new NameGeneratorFactory())->getGenerator();
  317. }
  318. /**
  319. * Returns a time converter configured for this environment
  320. */
  321. private function buildTimeConverter(CalculatorInterface $calculator): TimeConverterInterface
  322. {
  323. $genericConverter = new GenericTimeConverter($calculator);
  324. if ($this->is64BitSystem()) {
  325. return new PhpTimeConverter($calculator, $genericConverter);
  326. }
  327. return $genericConverter;
  328. }
  329. /**
  330. * Returns a UUID builder configured for this environment
  331. *
  332. * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec
  333. */
  334. private function buildUuidBuilder(bool $useGuids = false): UuidBuilderInterface
  335. {
  336. if ($useGuids) {
  337. return new GuidBuilder($this->numberConverter, $this->timeConverter);
  338. }
  339. return new FallbackBuilder([
  340. new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter),
  341. new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter),
  342. ]);
  343. }
  344. /**
  345. * Returns true if the PHP build is 64-bit
  346. */
  347. private function is64BitSystem(): bool
  348. {
  349. return PHP_INT_SIZE === 8 && !$this->force32Bit;
  350. }
  351. }