These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Nwidart\Modules\Commands; |
||
4 | |||
5 | use Illuminate\Console\Command; |
||
6 | use Illuminate\Contracts\Debug\ExceptionHandler; |
||
7 | use Illuminate\Support\Str; |
||
8 | use Nwidart\Modules\Contracts\RepositoryInterface; |
||
9 | use Nwidart\Modules\Module; |
||
10 | use Nwidart\Modules\Support\Config\GenerateConfigReader; |
||
11 | use Nwidart\Modules\Traits\ModuleCommandTrait; |
||
12 | use RuntimeException; |
||
13 | use Symfony\Component\Console\Input\InputArgument; |
||
14 | use Symfony\Component\Console\Input\InputOption; |
||
15 | |||
16 | class SeedCommand extends Command |
||
17 | { |
||
18 | use ModuleCommandTrait; |
||
19 | |||
20 | /** |
||
21 | * The console command name. |
||
22 | * |
||
23 | * @var string |
||
24 | */ |
||
25 | protected $name = 'module:seed'; |
||
26 | |||
27 | /** |
||
28 | * The console command description. |
||
29 | * |
||
30 | * @var string |
||
31 | */ |
||
32 | protected $description = 'Run database seeder from the specified module or from all modules.'; |
||
33 | |||
34 | /** |
||
35 | * Execute the console command. |
||
36 | * @throws FatalThrowableError |
||
37 | */ |
||
38 | public function handle() |
||
39 | { |
||
40 | try { |
||
41 | if ($name = $this->argument('module')) { |
||
42 | $name = Str::studly($name); |
||
0 ignored issues
–
show
|
|||
43 | $this->moduleSeed($this->getModuleByName($name)); |
||
0 ignored issues
–
show
It seems like
$this->getModuleByName($name) can be null ; however, moduleSeed() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
Loading history...
|
|||
44 | } else { |
||
45 | $modules = $this->getModuleRepository()->getOrdered(); |
||
46 | array_walk($modules, [$this, 'moduleSeed']); |
||
47 | $this->info('All modules seeded.'); |
||
48 | } |
||
49 | } catch (\Throwable $e) { |
||
50 | $this->reportException($e); |
||
51 | |||
52 | $this->renderException($this->getOutput(), $e); |
||
53 | |||
54 | return 1; |
||
55 | } |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * @throws RuntimeException |
||
60 | * @return RepositoryInterface |
||
61 | */ |
||
62 | public function getModuleRepository(): RepositoryInterface |
||
63 | { |
||
64 | $modules = $this->laravel['modules']; |
||
65 | if (!$modules instanceof RepositoryInterface) { |
||
66 | throw new RuntimeException('Module repository not found!'); |
||
67 | } |
||
68 | |||
69 | return $modules; |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * @param $name |
||
74 | * |
||
75 | * @throws RuntimeException |
||
76 | * |
||
77 | * @return Module |
||
78 | */ |
||
79 | public function getModuleByName($name) |
||
80 | { |
||
81 | $modules = $this->getModuleRepository(); |
||
82 | if ($modules->has($name) === false) { |
||
83 | throw new RuntimeException("Module [$name] does not exists."); |
||
84 | } |
||
85 | |||
86 | return $modules->find($name); |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * @param Module $module |
||
91 | * |
||
92 | * @return void |
||
93 | */ |
||
94 | public function moduleSeed(Module $module) |
||
95 | { |
||
96 | $seeders = []; |
||
97 | $name = $module->getName(); |
||
98 | $config = $module->get('migration'); |
||
99 | if (is_array($config) && array_key_exists('seeds', $config)) { |
||
100 | foreach ((array)$config['seeds'] as $class) { |
||
101 | if (class_exists($class)) { |
||
102 | $seeders[] = $class; |
||
103 | } |
||
104 | } |
||
105 | } else { |
||
106 | $class = $this->getSeederName($name); //legacy support |
||
107 | if (class_exists($class)) { |
||
108 | $seeders[] = $class; |
||
109 | } else { |
||
110 | //look at other namespaces |
||
111 | $classes = $this->getSeederNames($name); |
||
112 | foreach ($classes as $class) { |
||
113 | if (class_exists($class)) { |
||
114 | $seeders[] = $class; |
||
115 | } |
||
116 | } |
||
117 | } |
||
118 | } |
||
119 | |||
120 | if (count($seeders) > 0) { |
||
121 | array_walk($seeders, [$this, 'dbSeed']); |
||
122 | $this->info("Module [$name] seeded."); |
||
123 | } |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Seed the specified module. |
||
128 | * |
||
129 | * @param string $className |
||
130 | */ |
||
131 | protected function dbSeed($className) |
||
132 | { |
||
133 | if ($option = $this->option('class')) { |
||
134 | $params['--class'] = Str::finish(substr($className, 0, strrpos($className, '\\')), '\\') . $option; |
||
135 | } else { |
||
136 | $params = ['--class' => $className]; |
||
137 | } |
||
138 | |||
139 | if ($option = $this->option('database')) { |
||
140 | $params['--database'] = $option; |
||
141 | } |
||
142 | |||
143 | if ($option = $this->option('force')) { |
||
144 | $params['--force'] = $option; |
||
145 | } |
||
146 | |||
147 | $this->call('db:seed', $params); |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Get master database seeder name for the specified module. |
||
152 | * |
||
153 | * @param string $name |
||
154 | * |
||
155 | * @return string |
||
156 | */ |
||
157 | public function getSeederName($name) |
||
158 | { |
||
159 | $name = Str::studly($name); |
||
160 | |||
161 | $namespace = $this->laravel['modules']->config('namespace'); |
||
162 | $config = GenerateConfigReader::read('seeder'); |
||
163 | $seederPath = str_replace('/', '\\', $config->getPath()); |
||
164 | |||
165 | return $namespace . '\\' . $name . '\\' . $config->getNamespace() . '\\' . $name . 'DatabaseSeeder'; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Get master database seeder name for the specified module under a different namespace than Modules. |
||
170 | * |
||
171 | * @param string $name |
||
172 | * |
||
173 | * @return array $foundModules array containing namespace paths |
||
174 | */ |
||
175 | public function getSeederNames($name) |
||
176 | { |
||
177 | $name = Str::studly($name); |
||
178 | |||
179 | $seederPath = GenerateConfigReader::read('seeder'); |
||
180 | $seederPath = str_replace('/', '\\', $seederPath->getPath()); |
||
181 | |||
182 | $foundModules = []; |
||
183 | foreach ($this->laravel['modules']->config('scan.paths') as $path) { |
||
184 | $namespace = array_slice(explode('/', $path), -1)[0]; |
||
185 | $foundModules[] = $namespace . '\\' . $name . '\\' . $seederPath . '\\' . $name . 'DatabaseSeeder'; |
||
186 | } |
||
187 | |||
188 | return $foundModules; |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * Report the exception to the exception handler. |
||
193 | * |
||
194 | * @param \Symfony\Component\Console\Output\OutputInterface $output |
||
195 | * @param \Throwable $e |
||
196 | * @return void |
||
197 | */ |
||
198 | protected function renderException($output, \Throwable $e) |
||
199 | { |
||
200 | $this->laravel[ExceptionHandler::class]->renderForConsole($output, $e); |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Report the exception to the exception handler. |
||
205 | * |
||
206 | * @param \Throwable $e |
||
207 | * @return void |
||
208 | */ |
||
209 | protected function reportException(\Throwable $e) |
||
210 | { |
||
211 | $this->laravel[ExceptionHandler::class]->report($e); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Get the console command arguments. |
||
216 | * |
||
217 | * @return array |
||
218 | */ |
||
219 | 120 | protected function getArguments() |
|
220 | { |
||
221 | return [ |
||
222 | 120 | ['module', InputArgument::OPTIONAL, 'The name of module will be used.'], |
|
223 | ]; |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * Get the console command options. |
||
228 | * |
||
229 | * @return array |
||
230 | */ |
||
231 | 120 | View Code Duplication | protected function getOptions() |
232 | { |
||
233 | return [ |
||
234 | 120 | ['class', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder.'], |
|
235 | ['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to seed.'], |
||
236 | ['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'], |
||
237 | ]; |
||
238 | } |
||
239 | } |
||
240 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.