Completed
Push — master ( 50c5d9...acfd7d )
by Nicolas
13s queued 11s
created

SeedCommand::moduleSeed()   B

Complexity

Conditions 9
Paths 10

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
nc 10
nop 1
dl 0
loc 31
ccs 0
cts 19
cp 0
crap 90
rs 8.0555
c 0
b 0
f 0
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);
43
                $this->moduleSeed($this->getModuleByName($name));
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();
0 ignored issues
show
Bug introduced by
Consider using $module->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
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;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
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
        $seederPath = GenerateConfigReader::read('seeder');
163
        $seederPath = str_replace('/', '\\', $seederPath->getPath());
164
165
        return $namespace . '\\' . $name . '\\' . $seederPath . '\\' . $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 95
    protected function getArguments()
220
    {
221
        return [
222 95
            ['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 95 View Code Duplication
    protected function getOptions()
232
    {
233
        return [
234 95
            ['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