您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Facade.php 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. namespace Illuminate\Support\Facades;
  3. use Closure;
  4. use Mockery;
  5. use RuntimeException;
  6. use Mockery\MockInterface;
  7. abstract class Facade
  8. {
  9. /**
  10. * The application instance being facaded.
  11. *
  12. * @var \Illuminate\Contracts\Foundation\Application
  13. */
  14. protected static $app;
  15. /**
  16. * The resolved object instances.
  17. *
  18. * @var array
  19. */
  20. protected static $resolvedInstance;
  21. /**
  22. * Run a Closure when the facade has been resolved.
  23. *
  24. * @param \Closure $callback
  25. * @return void
  26. */
  27. public static function resolved(Closure $callback)
  28. {
  29. static::$app->afterResolving(static::getFacadeAccessor(), function ($service) use ($callback) {
  30. $callback($service);
  31. });
  32. }
  33. /**
  34. * Convert the facade into a Mockery spy.
  35. *
  36. * @return \Mockery\MockInterface
  37. */
  38. public static function spy()
  39. {
  40. if (! static::isMock()) {
  41. $class = static::getMockableClass();
  42. return tap($class ? Mockery::spy($class) : Mockery::spy(), function ($spy) {
  43. static::swap($spy);
  44. });
  45. }
  46. }
  47. /**
  48. * Initiate a mock expectation on the facade.
  49. *
  50. * @return \Mockery\Expectation
  51. */
  52. public static function shouldReceive()
  53. {
  54. $name = static::getFacadeAccessor();
  55. $mock = static::isMock()
  56. ? static::$resolvedInstance[$name]
  57. : static::createFreshMockInstance();
  58. return $mock->shouldReceive(...func_get_args());
  59. }
  60. /**
  61. * Create a fresh mock instance for the given class.
  62. *
  63. * @return \Mockery\Expectation
  64. */
  65. protected static function createFreshMockInstance()
  66. {
  67. return tap(static::createMock(), function ($mock) {
  68. static::swap($mock);
  69. $mock->shouldAllowMockingProtectedMethods();
  70. });
  71. }
  72. /**
  73. * Create a fresh mock instance for the given class.
  74. *
  75. * @return \Mockery\MockInterface
  76. */
  77. protected static function createMock()
  78. {
  79. $class = static::getMockableClass();
  80. return $class ? Mockery::mock($class) : Mockery::mock();
  81. }
  82. /**
  83. * Determines whether a mock is set as the instance of the facade.
  84. *
  85. * @return bool
  86. */
  87. protected static function isMock()
  88. {
  89. $name = static::getFacadeAccessor();
  90. return isset(static::$resolvedInstance[$name]) &&
  91. static::$resolvedInstance[$name] instanceof MockInterface;
  92. }
  93. /**
  94. * Get the mockable class for the bound instance.
  95. *
  96. * @return string|null
  97. */
  98. protected static function getMockableClass()
  99. {
  100. if ($root = static::getFacadeRoot()) {
  101. return get_class($root);
  102. }
  103. }
  104. /**
  105. * Hotswap the underlying instance behind the facade.
  106. *
  107. * @param mixed $instance
  108. * @return void
  109. */
  110. public static function swap($instance)
  111. {
  112. static::$resolvedInstance[static::getFacadeAccessor()] = $instance;
  113. if (isset(static::$app)) {
  114. static::$app->instance(static::getFacadeAccessor(), $instance);
  115. }
  116. }
  117. /**
  118. * Get the root object behind the facade.
  119. *
  120. * @return mixed
  121. */
  122. public static function getFacadeRoot()
  123. {
  124. return static::resolveFacadeInstance(static::getFacadeAccessor());
  125. }
  126. /**
  127. * Get the registered name of the component.
  128. *
  129. * @return string
  130. *
  131. * @throws \RuntimeException
  132. */
  133. protected static function getFacadeAccessor()
  134. {
  135. throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
  136. }
  137. /**
  138. * Resolve the facade root instance from the container.
  139. *
  140. * @param object|string $name
  141. * @return mixed
  142. */
  143. protected static function resolveFacadeInstance($name)
  144. {
  145. if (is_object($name)) {
  146. return $name;
  147. }
  148. if (isset(static::$resolvedInstance[$name])) {
  149. return static::$resolvedInstance[$name];
  150. }
  151. return static::$resolvedInstance[$name] = static::$app[$name];
  152. }
  153. /**
  154. * Clear a resolved facade instance.
  155. *
  156. * @param string $name
  157. * @return void
  158. */
  159. public static function clearResolvedInstance($name)
  160. {
  161. unset(static::$resolvedInstance[$name]);
  162. }
  163. /**
  164. * Clear all of the resolved instances.
  165. *
  166. * @return void
  167. */
  168. public static function clearResolvedInstances()
  169. {
  170. static::$resolvedInstance = [];
  171. }
  172. /**
  173. * Get the application instance behind the facade.
  174. *
  175. * @return \Illuminate\Contracts\Foundation\Application
  176. */
  177. public static function getFacadeApplication()
  178. {
  179. return static::$app;
  180. }
  181. /**
  182. * Set the application instance.
  183. *
  184. * @param \Illuminate\Contracts\Foundation\Application $app
  185. * @return void
  186. */
  187. public static function setFacadeApplication($app)
  188. {
  189. static::$app = $app;
  190. }
  191. /**
  192. * Handle dynamic, static calls to the object.
  193. *
  194. * @param string $method
  195. * @param array $args
  196. * @return mixed
  197. *
  198. * @throws \RuntimeException
  199. */
  200. public static function __callStatic($method, $args)
  201. {
  202. $instance = static::getFacadeRoot();
  203. if (! $instance) {
  204. throw new RuntimeException('A facade root has not been set.');
  205. }
  206. return $instance->$method(...$args);
  207. }
  208. }