GeneratorCommand.php 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. namespace Illuminate\Console;
  3. use Illuminate\Support\Str;
  4. use Illuminate\Filesystem\Filesystem;
  5. use Symfony\Component\Console\Input\InputArgument;
  6. abstract class GeneratorCommand extends Command
  7. {
  8. /**
  9. * The filesystem instance.
  10. *
  11. * @var \Illuminate\Filesystem\Filesystem
  12. */
  13. protected $files;
  14. /**
  15. * The type of class being generated.
  16. *
  17. * @var string
  18. */
  19. protected $type;
  20. /**
  21. * Create a new controller creator command instance.
  22. *
  23. * @param \Illuminate\Filesystem\Filesystem $files
  24. * @return void
  25. */
  26. public function __construct(Filesystem $files)
  27. {
  28. parent::__construct();
  29. $this->files = $files;
  30. }
  31. /**
  32. * Get the stub file for the generator.
  33. *
  34. * @return string
  35. */
  36. abstract protected function getStub();
  37. /**
  38. * Execute the console command.
  39. *
  40. * @return bool|null
  41. */
  42. public function handle()
  43. {
  44. $name = $this->qualifyClass($this->getNameInput());
  45. $path = $this->getPath($name);
  46. // First we will check to see if the class already exists. If it does, we don't want
  47. // to create the class and overwrite the user's code. So, we will bail out so the
  48. // code is untouched. Otherwise, we will continue generating this class' files.
  49. if ((! $this->hasOption('force') ||
  50. ! $this->option('force')) &&
  51. $this->alreadyExists($this->getNameInput())) {
  52. $this->error($this->type.' already exists!');
  53. return false;
  54. }
  55. // Next, we will generate the path to the location where this class' file should get
  56. // written. Then, we will build the class and make the proper replacements on the
  57. // stub files so that it gets the correctly formatted namespace and class name.
  58. $this->makeDirectory($path);
  59. $this->files->put($path, $this->buildClass($name));
  60. $this->info($this->type.' created successfully.');
  61. }
  62. /**
  63. * Parse the class name and format according to the root namespace.
  64. *
  65. * @param string $name
  66. * @return string
  67. */
  68. protected function qualifyClass($name)
  69. {
  70. $name = ltrim($name, '\\/');
  71. $rootNamespace = $this->rootNamespace();
  72. if (Str::startsWith($name, $rootNamespace)) {
  73. return $name;
  74. }
  75. $name = str_replace('/', '\\', $name);
  76. return $this->qualifyClass(
  77. $this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name
  78. );
  79. }
  80. /**
  81. * Get the default namespace for the class.
  82. *
  83. * @param string $rootNamespace
  84. * @return string
  85. */
  86. protected function getDefaultNamespace($rootNamespace)
  87. {
  88. return $rootNamespace;
  89. }
  90. /**
  91. * Determine if the class already exists.
  92. *
  93. * @param string $rawName
  94. * @return bool
  95. */
  96. protected function alreadyExists($rawName)
  97. {
  98. return $this->files->exists($this->getPath($this->qualifyClass($rawName)));
  99. }
  100. /**
  101. * Get the destination class path.
  102. *
  103. * @param string $name
  104. * @return string
  105. */
  106. protected function getPath($name)
  107. {
  108. $name = Str::replaceFirst($this->rootNamespace(), '', $name);
  109. return $this->laravel['path'].'/'.str_replace('\\', '/', $name).'.php';
  110. }
  111. /**
  112. * Build the directory for the class if necessary.
  113. *
  114. * @param string $path
  115. * @return string
  116. */
  117. protected function makeDirectory($path)
  118. {
  119. if (! $this->files->isDirectory(dirname($path))) {
  120. $this->files->makeDirectory(dirname($path), 0777, true, true);
  121. }
  122. return $path;
  123. }
  124. /**
  125. * Build the class with the given name.
  126. *
  127. * @param string $name
  128. * @return string
  129. */
  130. protected function buildClass($name)
  131. {
  132. $stub = $this->files->get($this->getStub());
  133. return $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
  134. }
  135. /**
  136. * Replace the namespace for the given stub.
  137. *
  138. * @param string $stub
  139. * @param string $name
  140. * @return $this
  141. */
  142. protected function replaceNamespace(&$stub, $name)
  143. {
  144. $stub = str_replace(
  145. ['DummyNamespace', 'DummyRootNamespace', 'NamespacedDummyUserModel'],
  146. [$this->getNamespace($name), $this->rootNamespace(), config('auth.providers.users.model')],
  147. $stub
  148. );
  149. return $this;
  150. }
  151. /**
  152. * Get the full namespace for a given class, without the class name.
  153. *
  154. * @param string $name
  155. * @return string
  156. */
  157. protected function getNamespace($name)
  158. {
  159. return trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
  160. }
  161. /**
  162. * Replace the class name for the given stub.
  163. *
  164. * @param string $stub
  165. * @param string $name
  166. * @return string
  167. */
  168. protected function replaceClass($stub, $name)
  169. {
  170. $class = str_replace($this->getNamespace($name).'\\', '', $name);
  171. return str_replace('DummyClass', $class, $stub);
  172. }
  173. /**
  174. * Get the desired class name from the input.
  175. *
  176. * @return string
  177. */
  178. protected function getNameInput()
  179. {
  180. return trim($this->argument('name'));
  181. }
  182. /**
  183. * Get the root namespace for the class.
  184. *
  185. * @return string
  186. */
  187. protected function rootNamespace()
  188. {
  189. return $this->laravel->getNamespace();
  190. }
  191. /**
  192. * Get the console command arguments.
  193. *
  194. * @return array
  195. */
  196. protected function getArguments()
  197. {
  198. return [
  199. ['name', InputArgument::REQUIRED, 'The name of the class'],
  200. ];
  201. }
  202. }