/vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php

https://gitlab.com/jjpa2018/dashboard · PHP · 210 lines · 88 code · 27 blank · 95 comment · 9 complexity · 3960549ed318d27107624d48dbfec982 MD5 · raw file

  1. <?php
  2. namespace Illuminate\Foundation;
  3. use Exception;
  4. use Illuminate\Contracts\Foundation\Application as ApplicationContract;
  5. use Illuminate\Filesystem\Filesystem;
  6. class ProviderRepository
  7. {
  8. /**
  9. * The application implementation.
  10. *
  11. * @var \Illuminate\Contracts\Foundation\Application
  12. */
  13. protected $app;
  14. /**
  15. * The filesystem instance.
  16. *
  17. * @var \Illuminate\Filesystem\Filesystem
  18. */
  19. protected $files;
  20. /**
  21. * The path to the manifest file.
  22. *
  23. * @var string
  24. */
  25. protected $manifestPath;
  26. /**
  27. * Create a new service repository instance.
  28. *
  29. * @param \Illuminate\Contracts\Foundation\Application $app
  30. * @param \Illuminate\Filesystem\Filesystem $files
  31. * @param string $manifestPath
  32. * @return void
  33. */
  34. public function __construct(ApplicationContract $app, Filesystem $files, $manifestPath)
  35. {
  36. $this->app = $app;
  37. $this->files = $files;
  38. $this->manifestPath = $manifestPath;
  39. }
  40. /**
  41. * Register the application service providers.
  42. *
  43. * @param array $providers
  44. * @return void
  45. */
  46. public function load(array $providers)
  47. {
  48. $manifest = $this->loadManifest();
  49. // First we will load the service manifest, which contains information on all
  50. // service providers registered with the application and which services it
  51. // provides. This is used to know which services are "deferred" loaders.
  52. if ($this->shouldRecompile($manifest, $providers)) {
  53. $manifest = $this->compileManifest($providers);
  54. }
  55. // Next, we will register events to load the providers for each of the events
  56. // that it has requested. This allows the service provider to defer itself
  57. // while still getting automatically loaded when a certain event occurs.
  58. foreach ($manifest['when'] as $provider => $events) {
  59. $this->registerLoadEvents($provider, $events);
  60. }
  61. // We will go ahead and register all of the eagerly loaded providers with the
  62. // application so their services can be registered with the application as
  63. // a provided service. Then we will set the deferred service list on it.
  64. foreach ($manifest['eager'] as $provider) {
  65. $this->app->register($provider);
  66. }
  67. $this->app->addDeferredServices($manifest['deferred']);
  68. }
  69. /**
  70. * Load the service provider manifest JSON file.
  71. *
  72. * @return array|null
  73. */
  74. public function loadManifest()
  75. {
  76. // The service manifest is a file containing a JSON representation of every
  77. // service provided by the application and whether its provider is using
  78. // deferred loading or should be eagerly loaded on each request to us.
  79. if ($this->files->exists($this->manifestPath)) {
  80. $manifest = $this->files->getRequire($this->manifestPath);
  81. if ($manifest) {
  82. return array_merge(['when' => []], $manifest);
  83. }
  84. }
  85. }
  86. /**
  87. * Determine if the manifest should be compiled.
  88. *
  89. * @param array $manifest
  90. * @param array $providers
  91. * @return bool
  92. */
  93. public function shouldRecompile($manifest, $providers)
  94. {
  95. return is_null($manifest) || $manifest['providers'] != $providers;
  96. }
  97. /**
  98. * Register the load events for the given provider.
  99. *
  100. * @param string $provider
  101. * @param array $events
  102. * @return void
  103. */
  104. protected function registerLoadEvents($provider, array $events)
  105. {
  106. if (count($events) < 1) {
  107. return;
  108. }
  109. $this->app->make('events')->listen($events, function () use ($provider) {
  110. $this->app->register($provider);
  111. });
  112. }
  113. /**
  114. * Compile the application service manifest file.
  115. *
  116. * @param array $providers
  117. * @return array
  118. */
  119. protected function compileManifest($providers)
  120. {
  121. // The service manifest should contain a list of all of the providers for
  122. // the application so we can compare it on each request to the service
  123. // and determine if the manifest should be recompiled or is current.
  124. $manifest = $this->freshManifest($providers);
  125. foreach ($providers as $provider) {
  126. $instance = $this->createProvider($provider);
  127. // When recompiling the service manifest, we will spin through each of the
  128. // providers and check if it's a deferred provider or not. If so we'll
  129. // add it's provided services to the manifest and note the provider.
  130. if ($instance->isDeferred()) {
  131. foreach ($instance->provides() as $service) {
  132. $manifest['deferred'][$service] = $provider;
  133. }
  134. $manifest['when'][$provider] = $instance->when();
  135. }
  136. // If the service providers are not deferred, we will simply add it to an
  137. // array of eagerly loaded providers that will get registered on every
  138. // request to this application instead of "lazy" loading every time.
  139. else {
  140. $manifest['eager'][] = $provider;
  141. }
  142. }
  143. return $this->writeManifest($manifest);
  144. }
  145. /**
  146. * Create a fresh service manifest data structure.
  147. *
  148. * @param array $providers
  149. * @return array
  150. */
  151. protected function freshManifest(array $providers)
  152. {
  153. return ['providers' => $providers, 'eager' => [], 'deferred' => []];
  154. }
  155. /**
  156. * Write the service manifest file to disk.
  157. *
  158. * @param array $manifest
  159. * @return array
  160. *
  161. * @throws \Exception
  162. */
  163. public function writeManifest($manifest)
  164. {
  165. if (! is_writable($dirname = dirname($this->manifestPath))) {
  166. throw new Exception("The {$dirname} directory must be present and writable.");
  167. }
  168. $this->files->replace(
  169. $this->manifestPath, '<?php return '.var_export($manifest, true).';'
  170. );
  171. return array_merge(['when' => []], $manifest);
  172. }
  173. /**
  174. * Create a new provider instance.
  175. *
  176. * @param string $provider
  177. * @return \Illuminate\Support\ServiceProvider
  178. */
  179. public function createProvider($provider)
  180. {
  181. return new $provider($this->app);
  182. }
  183. }