MultipleInstanceManager.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace Illuminate\Support;
  3. use Closure;
  4. use InvalidArgumentException;
  5. use RuntimeException;
  6. abstract class MultipleInstanceManager
  7. {
  8. /**
  9. * The application instance.
  10. *
  11. * @var \Illuminate\Contracts\Foundation\Application
  12. */
  13. protected $app;
  14. /**
  15. * The array of resolved instances.
  16. *
  17. * @var array
  18. */
  19. protected $instances = [];
  20. /**
  21. * The registered custom instance creators.
  22. *
  23. * @var array
  24. */
  25. protected $customCreators = [];
  26. /**
  27. * Create a new manager instance.
  28. *
  29. * @param \Illuminate\Contracts\Foundation\Application $app
  30. * @return void
  31. */
  32. public function __construct($app)
  33. {
  34. $this->app = $app;
  35. }
  36. /**
  37. * Get the default instance name.
  38. *
  39. * @return string
  40. */
  41. abstract public function getDefaultInstance();
  42. /**
  43. * Set the default instance name.
  44. *
  45. * @param string $name
  46. * @return void
  47. */
  48. abstract public function setDefaultInstance($name);
  49. /**
  50. * Get the instance specific configuration.
  51. *
  52. * @param string $name
  53. * @return array
  54. */
  55. abstract public function getInstanceConfig($name);
  56. /**
  57. * Get an instance instance by name.
  58. *
  59. * @param string|null $name
  60. * @return mixed
  61. */
  62. public function instance($name = null)
  63. {
  64. $name = $name ?: $this->getDefaultInstance();
  65. return $this->instances[$name] = $this->get($name);
  66. }
  67. /**
  68. * Attempt to get an instance from the local cache.
  69. *
  70. * @param string $name
  71. * @return mixed
  72. */
  73. protected function get($name)
  74. {
  75. return $this->instances[$name] ?? $this->resolve($name);
  76. }
  77. /**
  78. * Resolve the given instance.
  79. *
  80. * @param string $name
  81. * @return mixed
  82. *
  83. * @throws \InvalidArgumentException
  84. */
  85. protected function resolve($name)
  86. {
  87. $config = $this->getInstanceConfig($name);
  88. if (is_null($config)) {
  89. throw new InvalidArgumentException("Instance [{$name}] is not defined.");
  90. }
  91. if (! array_key_exists('driver', $config)) {
  92. throw new RuntimeException("Instance [{$name}] does not specify a driver.");
  93. }
  94. if (isset($this->customCreators[$config['driver']])) {
  95. return $this->callCustomCreator($config);
  96. } else {
  97. $driverMethod = 'create'.ucfirst($config['driver']).'Driver';
  98. if (method_exists($this, $driverMethod)) {
  99. return $this->{$driverMethod}($config);
  100. } else {
  101. throw new InvalidArgumentException("Instance driver [{$config['driver']}] is not supported.");
  102. }
  103. }
  104. }
  105. /**
  106. * Call a custom instance creator.
  107. *
  108. * @param array $config
  109. * @return mixed
  110. */
  111. protected function callCustomCreator(array $config)
  112. {
  113. return $this->customCreators[$config['driver']]($this->app, $config);
  114. }
  115. /**
  116. * Unset the given instances.
  117. *
  118. * @param array|string|null $name
  119. * @return $this
  120. */
  121. public function forgetInstance($name = null)
  122. {
  123. $name ??= $this->getDefaultInstance();
  124. foreach ((array) $name as $instanceName) {
  125. if (isset($this->instances[$instanceName])) {
  126. unset($this->instances[$instanceName]);
  127. }
  128. }
  129. return $this;
  130. }
  131. /**
  132. * Disconnect the given instance and remove from local cache.
  133. *
  134. * @param string|null $name
  135. * @return void
  136. */
  137. public function purge($name = null)
  138. {
  139. $name ??= $this->getDefaultInstance();
  140. unset($this->instances[$name]);
  141. }
  142. /**
  143. * Register a custom instance creator Closure.
  144. *
  145. * @param string $name
  146. * @param \Closure $callback
  147. * @return $this
  148. */
  149. public function extend($name, Closure $callback)
  150. {
  151. $this->customCreators[$name] = $callback->bindTo($this, $this);
  152. return $this;
  153. }
  154. /**
  155. * Dynamically call the default instance.
  156. *
  157. * @param string $method
  158. * @param array $parameters
  159. * @return mixed
  160. */
  161. public function __call($method, $parameters)
  162. {
  163. return $this->instance()->$method(...$parameters);
  164. }
  165. }