Completed
Push — master ( dd5aae...50210e )
by Nicolas
04:14
created

SeedCommand::getSeederName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 10
ccs 0
cts 6
cp 0
crap 2
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace Nwidart\Modules\Commands;
4
5
use ErrorException;
6
use Illuminate\Console\Command;
7
use Illuminate\Contracts\Debug\ExceptionHandler;
8
use Illuminate\Support\Str;
9
use Nwidart\Modules\Contracts\RepositoryInterface;
10
use Nwidart\Modules\Module;
11
use Nwidart\Modules\Support\Config\GenerateConfigReader;
12
use Nwidart\Modules\Traits\ModuleCommandTrait;
13
use RuntimeException;
14
use Symfony\Component\Console\Input\InputArgument;
15
use Symfony\Component\Console\Input\InputOption;
16
17
class SeedCommand extends Command
18
{
19
    use ModuleCommandTrait;
20
21
    /**
22
     * The console command name.
23
     *
24
     * @var string
25
     */
26
    protected $name = 'module:seed';
27
28
    /**
29
     * The console command description.
30
     *
31
     * @var string
32
     */
33
    protected $description = 'Run database seeder from the specified module or from all modules.';
34
35
    /**
36
     * Execute the console command.
37
     * @throws FatalThrowableError
38
     */
39
    public function handle()
40
    {
41
        try {
42
            if ($name = $this->argument('module')) {
43
                $name = Str::studly($name);
44
                $this->moduleSeed($this->getModuleByName($name));
45
            } else {
46
                $modules = $this->getModuleRepository()->getOrdered();
47
                array_walk($modules, [$this, 'moduleSeed']);
48
                $this->info('All modules seeded.');
49
            }
50
        } catch (\Error $e) {
51
            $e = new ErrorException($e->getMessage(), $e->getCode(), 1, $e->getFile(), $e->getLine(), $e);
52
            $this->reportException($e);
53
            $this->renderException($this->getOutput(), $e);
54
55
            return 1;
56
        } catch (\Exception $e) {
57
            $this->reportException($e);
58
            $this->renderException($this->getOutput(), $e);
59
60
            return 1;
61
        }
62
    }
63
64
    /**
65
     * @throws RuntimeException
66
     * @return RepositoryInterface
67
     */
68
    public function getModuleRepository(): RepositoryInterface
69
    {
70
        $modules = $this->laravel['modules'];
71
        if (!$modules instanceof RepositoryInterface) {
72
            throw new RuntimeException('Module repository not found!');
73
        }
74
75
        return $modules;
76
    }
77
78
    /**
79
     * @param $name
80
     *
81
     * @throws RuntimeException
82
     *
83
     * @return Module
84
     */
85
    public function getModuleByName($name)
86
    {
87
        $modules = $this->getModuleRepository();
88
        if ($modules->has($name) === false) {
89
            throw new RuntimeException("Module [$name] does not exists.");
90
        }
91
92
        return $modules->find($name);
93
    }
94
95
    /**
96
     * @param Module $module
97
     *
98
     * @return void
99
     */
100
    public function moduleSeed(Module $module)
101
    {
102
        $seeders = [];
103
        $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...
104
        $config = $module->get('migration');
105
        if (is_array($config) && array_key_exists('seeds', $config)) {
106
            foreach ((array)$config['seeds'] as $class) {
107
                if (class_exists($class)) {
108
                    $seeders[] = $class;
109
                }
110
            }
111
        } else {
112
            $class = $this->getSeederName($name); //legacy support
113
            if (class_exists($class)) {
114
                $seeders[] = $class;
115
            } else {
116
                //look at other namespaces
117
                $classes = $this->getSeederNames($name);
118
                foreach ($classes as $class) {
119
                    if (class_exists($class)) {
120
                        $seeders[] = $class;
121
                    }
122
                }
123
            }
124
        }
125
126
        if (count($seeders) > 0) {
127
            array_walk($seeders, [$this, 'dbSeed']);
128
            $this->info("Module [$name] seeded.");
129
        }
130
    }
131
132
    /**
133
     * Seed the specified module.
134
     *
135
     * @param string $className
136
     */
137
    protected function dbSeed($className)
138
    {
139
        if ($option = $this->option('class')) {
140
            $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...
141
        } else {
142
            $params = ['--class' => $className];
143
        }
144
145
        if ($option = $this->option('database')) {
146
            $params['--database'] = $option;
147
        }
148
149
        if ($option = $this->option('force')) {
150
            $params['--force'] = $option;
151
        }
152
153
        $this->call('db:seed', $params);
154
    }
155
156
    /**
157
     * Get master database seeder name for the specified module.
158
     *
159
     * @param string $name
160
     *
161
     * @return string
162
     */
163
    public function getSeederName($name)
164
    {
165
        $name = Str::studly($name);
166
167
        $namespace = $this->laravel['modules']->config('namespace');
168
        $config = GenerateConfigReader::read('seeder');
169
        $seederPath = str_replace('/', '\\', $config->getPath());
170
171
        return $namespace . '\\' . $name . '\\' . $seederPath . '\\' . $name . 'DatabaseSeeder';
172
    }
173
174
    /**
175
     * Get master database seeder name for the specified module under a different namespace than Modules.
176
     *
177
     * @param string $name
178
     *
179
     * @return array $foundModules array containing namespace paths
180
     */
181
    public function getSeederNames($name)
182
    {
183
        $name = Str::studly($name);
184
185
        $seederPath = GenerateConfigReader::read('seeder');
186
        $seederPath = str_replace('/', '\\', $seederPath->getPath());
187
188
        $foundModules = [];
189
        foreach ($this->laravel['modules']->config('scan.paths') as $path) {
190
            $namespace = array_slice(explode('/', $path), -1)[0];
191
            $foundModules[] = $namespace . '\\' . $name . '\\' . $seederPath . '\\' . $name . 'DatabaseSeeder';
192
        }
193
194
        return $foundModules;
195
    }
196
197
    /**
198
     * Report the exception to the exception handler.
199
     *
200
     * @param  \Symfony\Component\Console\Output\OutputInterface  $output
201
     * @param  \Throwable  $e
202
     * @return void
203
     */
204
    protected function renderException($output, \Exception $e)
205
    {
206
        $this->laravel[ExceptionHandler::class]->renderForConsole($output, $e);
207
    }
208
209
    /**
210
     * Report the exception to the exception handler.
211
     *
212
     * @param  \Throwable  $e
213
     * @return void
214
     */
215
    protected function reportException(\Exception $e)
216
    {
217
        $this->laravel[ExceptionHandler::class]->report($e);
218
    }
219
220
    /**
221
     * Get the console command arguments.
222
     *
223
     * @return array
224
     */
225 121
    protected function getArguments()
226
    {
227
        return [
228 121
            ['module', InputArgument::OPTIONAL, 'The name of module will be used.'],
229
        ];
230
    }
231
232
    /**
233
     * Get the console command options.
234
     *
235
     * @return array
236
     */
237 121 View Code Duplication
    protected function getOptions()
238
    {
239
        return [
240 121
            ['class', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder.'],
241
            ['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to seed.'],
242
            ['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'],
243
        ];
244
    }
245
}
246